inst_queue_impl.hh revision 1061
111988Sandreas.sandberg@arm.com#ifndef __INST_QUEUE_IMPL_HH__
211988Sandreas.sandberg@arm.com#define __INST_QUEUE_IMPL_HH__
311988Sandreas.sandberg@arm.com
411988Sandreas.sandberg@arm.com// Todo:
511988Sandreas.sandberg@arm.com// Current ordering allows for 0 cycle added-to-scheduled.  Could maybe fake
611988Sandreas.sandberg@arm.com// it; either do in reverse order, or have added instructions put into a
711988Sandreas.sandberg@arm.com// different ready queue that, in scheduleRreadyInsts(), gets put onto the
811988Sandreas.sandberg@arm.com// normal ready queue.  This would however give only a one cycle delay,
911988Sandreas.sandberg@arm.com// but probably is more flexible to actually add in a delay parameter than
1011988Sandreas.sandberg@arm.com// just running it backwards.
1111988Sandreas.sandberg@arm.com
1211988Sandreas.sandberg@arm.com#include <vector>
1311988Sandreas.sandberg@arm.com
1411988Sandreas.sandberg@arm.com#include "sim/universe.hh"
1511988Sandreas.sandberg@arm.com#include "cpu/beta_cpu/inst_queue.hh"
1611988Sandreas.sandberg@arm.com
1711988Sandreas.sandberg@arm.com// Either compile error or max int due to sign extension.
1811988Sandreas.sandberg@arm.com// Blatant hack to avoid compile warnings.
1911988Sandreas.sandberg@arm.comconst InstSeqNum MaxInstSeqNum = 0 - 1;
2011988Sandreas.sandberg@arm.com
2111988Sandreas.sandberg@arm.comtemplate <class Impl>
2211988Sandreas.sandberg@arm.comInstructionQueue<Impl>::InstructionQueue(Params &params)
2311988Sandreas.sandberg@arm.com    : memDepUnit(params),
2411988Sandreas.sandberg@arm.com      numEntries(params.numIQEntries),
2511988Sandreas.sandberg@arm.com      intWidth(params.executeIntWidth),
2611988Sandreas.sandberg@arm.com      floatWidth(params.executeFloatWidth),
2711988Sandreas.sandberg@arm.com      totalWidth(params.issueWidth),
2811988Sandreas.sandberg@arm.com      numPhysIntRegs(params.numPhysIntRegs),
2911988Sandreas.sandberg@arm.com      numPhysFloatRegs(params.numPhysFloatRegs),
3011988Sandreas.sandberg@arm.com      commitToIEWDelay(params.commitToIEWDelay)
3111988Sandreas.sandberg@arm.com{
3211988Sandreas.sandberg@arm.com    // HACK: HARDCODED NUMBER.  REMOVE LATER AND ADD TO PARAMETER.
3311988Sandreas.sandberg@arm.com    branchWidth = 1;
3411988Sandreas.sandberg@arm.com    memoryWidth = 1;
3511988Sandreas.sandberg@arm.com
3611988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Int width is %i.\n", params.executeIntWidth);
3711988Sandreas.sandberg@arm.com
3811988Sandreas.sandberg@arm.com    // Initialize the number of free IQ entries.
3911988Sandreas.sandberg@arm.com    freeEntries = numEntries;
4011988Sandreas.sandberg@arm.com
4111988Sandreas.sandberg@arm.com    // Set the number of physical registers as the number of int + float
4211988Sandreas.sandberg@arm.com    numPhysRegs = numPhysIntRegs + numPhysFloatRegs;
4311988Sandreas.sandberg@arm.com
4411988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
4511988Sandreas.sandberg@arm.com
4611988Sandreas.sandberg@arm.com    //Create an entry for each physical register within the
4711988Sandreas.sandberg@arm.com    //dependency graph.
4811988Sandreas.sandberg@arm.com    dependGraph = new DependencyEntry[numPhysRegs];
4912035Sandreas.sandberg@arm.com
5012035Sandreas.sandberg@arm.com    // Resize the register scoreboard.
5111988Sandreas.sandberg@arm.com    regScoreboard.resize(numPhysRegs);
5211988Sandreas.sandberg@arm.com
5311988Sandreas.sandberg@arm.com    // Initialize all the head pointers to point to NULL, and all the
5411988Sandreas.sandberg@arm.com    // entries as unready.
5511988Sandreas.sandberg@arm.com    // Note that in actuality, the registers corresponding to the logical
5611988Sandreas.sandberg@arm.com    // registers start off as ready.  However this doesn't matter for the
5711988Sandreas.sandberg@arm.com    // IQ as the instruction should have been correctly told if those
5811988Sandreas.sandberg@arm.com    // registers are ready in rename.  Thus it can all be initialized as
5911988Sandreas.sandberg@arm.com    // unready.
6011988Sandreas.sandberg@arm.com    for (int i = 0; i < numPhysRegs; ++i)
6111988Sandreas.sandberg@arm.com    {
6211988Sandreas.sandberg@arm.com        dependGraph[i].next = NULL;
6311988Sandreas.sandberg@arm.com        dependGraph[i].inst = NULL;
6411988Sandreas.sandberg@arm.com        regScoreboard[i] = false;
6511988Sandreas.sandberg@arm.com    }
6611988Sandreas.sandberg@arm.com
6711988Sandreas.sandberg@arm.com}
6811988Sandreas.sandberg@arm.com
6911988Sandreas.sandberg@arm.comtemplate <class Impl>
7011988Sandreas.sandberg@arm.comvoid
7111988Sandreas.sandberg@arm.comInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
7211988Sandreas.sandberg@arm.com{
7311988Sandreas.sandberg@arm.com    cpu = cpu_ptr;
7411988Sandreas.sandberg@arm.com
7511988Sandreas.sandberg@arm.com    tail = cpu->instList.begin();
7611988Sandreas.sandberg@arm.com}
7711988Sandreas.sandberg@arm.com
7811988Sandreas.sandberg@arm.comtemplate <class Impl>
7911988Sandreas.sandberg@arm.comvoid
8011988Sandreas.sandberg@arm.comInstructionQueue<Impl>::setIssueToExecuteQueue(
8111988Sandreas.sandberg@arm.com                        TimeBuffer<IssueStruct> *i2e_ptr)
8211988Sandreas.sandberg@arm.com{
8311988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
8411988Sandreas.sandberg@arm.com    issueToExecuteQueue = i2e_ptr;
8511988Sandreas.sandberg@arm.com}
8611988Sandreas.sandberg@arm.com
8711988Sandreas.sandberg@arm.comtemplate <class Impl>
8811988Sandreas.sandberg@arm.comvoid
8911988Sandreas.sandberg@arm.comInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
9011988Sandreas.sandberg@arm.com{
9111988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Set the time buffer.\n");
9211988Sandreas.sandberg@arm.com    timeBuffer = tb_ptr;
9311988Sandreas.sandberg@arm.com
9411988Sandreas.sandberg@arm.com    fromCommit = timeBuffer->getWire(-commitToIEWDelay);
9511988Sandreas.sandberg@arm.com}
9611988Sandreas.sandberg@arm.com
9711988Sandreas.sandberg@arm.com// Might want to do something more complex if it knows how many instructions
9811988Sandreas.sandberg@arm.com// will be issued this cycle.
9911988Sandreas.sandberg@arm.comtemplate <class Impl>
10011988Sandreas.sandberg@arm.combool
10111988Sandreas.sandberg@arm.comInstructionQueue<Impl>::isFull()
10211988Sandreas.sandberg@arm.com{
10311988Sandreas.sandberg@arm.com    if (freeEntries == 0) {
10411988Sandreas.sandberg@arm.com        return(true);
10511988Sandreas.sandberg@arm.com    } else {
10611988Sandreas.sandberg@arm.com        return(false);
10711988Sandreas.sandberg@arm.com    }
10811988Sandreas.sandberg@arm.com}
10911988Sandreas.sandberg@arm.com
11011988Sandreas.sandberg@arm.comtemplate <class Impl>
11111988Sandreas.sandberg@arm.comunsigned
11211988Sandreas.sandberg@arm.comInstructionQueue<Impl>::numFreeEntries()
11311988Sandreas.sandberg@arm.com{
11411988Sandreas.sandberg@arm.com    return freeEntries;
11511988Sandreas.sandberg@arm.com}
11611988Sandreas.sandberg@arm.com
11711988Sandreas.sandberg@arm.comtemplate <class Impl>
11811988Sandreas.sandberg@arm.comvoid
11911988Sandreas.sandberg@arm.comInstructionQueue<Impl>::insert(DynInstPtr &new_inst)
12011988Sandreas.sandberg@arm.com{
12111988Sandreas.sandberg@arm.com    // Make sure the instruction is valid
12211988Sandreas.sandberg@arm.com    assert(new_inst);
12311988Sandreas.sandberg@arm.com
12411988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
12511988Sandreas.sandberg@arm.com            new_inst->readPC());
12611988Sandreas.sandberg@arm.com
12711988Sandreas.sandberg@arm.com    // Check if there are any free entries.  Panic if there are none.
12811988Sandreas.sandberg@arm.com    // Might want to have this return a fault in the future instead of
12911988Sandreas.sandberg@arm.com    // panicing.
13011988Sandreas.sandberg@arm.com    assert(freeEntries != 0);
13111988Sandreas.sandberg@arm.com
13211988Sandreas.sandberg@arm.com    // If the IQ currently has nothing in it, then there's a possibility
13311988Sandreas.sandberg@arm.com    // that the tail iterator is invalid (might have been pointing at an
13411988Sandreas.sandberg@arm.com    // instruction that was retired).  Reset the tail iterator.
13512036Sandreas.sandberg@arm.com    if (freeEntries == numEntries) {
13612036Sandreas.sandberg@arm.com        tail = cpu->instList.begin();
13711988Sandreas.sandberg@arm.com    }
13811988Sandreas.sandberg@arm.com
13911988Sandreas.sandberg@arm.com    // Move the tail iterator.  Instructions may not have been issued
14011988Sandreas.sandberg@arm.com    // to the IQ, so we may have to increment the iterator more than once.
14111988Sandreas.sandberg@arm.com    while ((*tail) != new_inst) {
14211988Sandreas.sandberg@arm.com        tail++;
14311988Sandreas.sandberg@arm.com
14411988Sandreas.sandberg@arm.com        // Make sure the tail iterator points at something legal.
14511988Sandreas.sandberg@arm.com        assert(tail != cpu->instList.end());
14611988Sandreas.sandberg@arm.com    }
14711988Sandreas.sandberg@arm.com
14811988Sandreas.sandberg@arm.com
14911988Sandreas.sandberg@arm.com    // Decrease the number of free entries.
15011988Sandreas.sandberg@arm.com    --freeEntries;
15111988Sandreas.sandberg@arm.com
15211988Sandreas.sandberg@arm.com    // Look through its source registers (physical regs), and mark any
15311988Sandreas.sandberg@arm.com    // dependencies.
15411988Sandreas.sandberg@arm.com    addToDependents(new_inst);
15511988Sandreas.sandberg@arm.com
15611988Sandreas.sandberg@arm.com    // Have this instruction set itself as the producer of its destination
15711988Sandreas.sandberg@arm.com    // register(s).
15811988Sandreas.sandberg@arm.com    createDependency(new_inst);
15911988Sandreas.sandberg@arm.com
16011988Sandreas.sandberg@arm.com    // If it's a memory instruction, add it to the memory dependency
16111988Sandreas.sandberg@arm.com    // unit.
16211988Sandreas.sandberg@arm.com    if (new_inst->isMemRef()) {
16311988Sandreas.sandberg@arm.com        memDepUnit.insert(new_inst);
16411988Sandreas.sandberg@arm.com    }
16511988Sandreas.sandberg@arm.com
16611988Sandreas.sandberg@arm.com    // If the instruction is ready then add it to the ready list.
16711988Sandreas.sandberg@arm.com    addIfReady(new_inst);
16811988Sandreas.sandberg@arm.com
16912036Sandreas.sandberg@arm.com    assert(freeEntries == (numEntries - countInsts()));
17012035Sandreas.sandberg@arm.com}
17112035Sandreas.sandberg@arm.com
17212035Sandreas.sandberg@arm.comtemplate <class Impl>
17311988Sandreas.sandberg@arm.comvoid
17411988Sandreas.sandberg@arm.comInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
17511988Sandreas.sandberg@arm.com{
17611988Sandreas.sandberg@arm.com    nonSpecInsts[inst->seqNum] = inst;
17711988Sandreas.sandberg@arm.com
17811988Sandreas.sandberg@arm.com    // @todo: Clean up this code; can do it by setting inst as unable
17911988Sandreas.sandberg@arm.com    // to issue, then calling normal insert on the inst.
18011988Sandreas.sandberg@arm.com
18111988Sandreas.sandberg@arm.com    // Make sure the instruction is valid
18211988Sandreas.sandberg@arm.com    assert(inst);
18311988Sandreas.sandberg@arm.com
18411988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
18511988Sandreas.sandberg@arm.com            inst->readPC());
18611988Sandreas.sandberg@arm.com
18711988Sandreas.sandberg@arm.com    // Check if there are any free entries.  Panic if there are none.
18811988Sandreas.sandberg@arm.com    // Might want to have this return a fault in the future instead of
18911988Sandreas.sandberg@arm.com    // panicing.
19011988Sandreas.sandberg@arm.com    assert(freeEntries != 0);
19111988Sandreas.sandberg@arm.com
19211988Sandreas.sandberg@arm.com    // If the IQ currently has nothing in it, then there's a possibility
19311988Sandreas.sandberg@arm.com    // that the tail iterator is invalid (might have been pointing at an
19411988Sandreas.sandberg@arm.com    // instruction that was retired).  Reset the tail iterator.
19511988Sandreas.sandberg@arm.com    if (freeEntries == numEntries) {
19611988Sandreas.sandberg@arm.com        tail = cpu->instList.begin();
19711988Sandreas.sandberg@arm.com    }
19811988Sandreas.sandberg@arm.com
19911988Sandreas.sandberg@arm.com    // Move the tail iterator.  Instructions may not have been issued
20011988Sandreas.sandberg@arm.com    // to the IQ, so we may have to increment the iterator more than once.
20111988Sandreas.sandberg@arm.com    while ((*tail) != inst) {
20211988Sandreas.sandberg@arm.com        tail++;
20311988Sandreas.sandberg@arm.com
20411988Sandreas.sandberg@arm.com        // Make sure the tail iterator points at something legal.
20511988Sandreas.sandberg@arm.com        assert(tail != cpu->instList.end());
20611988Sandreas.sandberg@arm.com    }
20711988Sandreas.sandberg@arm.com
20811988Sandreas.sandberg@arm.com    // Decrease the number of free entries.
20911988Sandreas.sandberg@arm.com    --freeEntries;
21011988Sandreas.sandberg@arm.com
21111988Sandreas.sandberg@arm.com    // Look through its source registers (physical regs), and mark any
21211988Sandreas.sandberg@arm.com    // dependencies.
21311988Sandreas.sandberg@arm.com//    addToDependents(inst);
21411988Sandreas.sandberg@arm.com
21511988Sandreas.sandberg@arm.com    // Have this instruction set itself as the producer of its destination
21611988Sandreas.sandberg@arm.com    // register(s).
21711988Sandreas.sandberg@arm.com    createDependency(inst);
21811988Sandreas.sandberg@arm.com
21911988Sandreas.sandberg@arm.com    // If it's a memory instruction, add it to the memory dependency
22011988Sandreas.sandberg@arm.com    // unit.
22111988Sandreas.sandberg@arm.com    if (inst->isMemRef()) {
22211988Sandreas.sandberg@arm.com        memDepUnit.insert(inst);
22311988Sandreas.sandberg@arm.com    }
22411988Sandreas.sandberg@arm.com}
22511988Sandreas.sandberg@arm.com
22611988Sandreas.sandberg@arm.com// Slightly hack function to advance the tail iterator in the case that
22711988Sandreas.sandberg@arm.com// the IEW stage issues an instruction that is not added to the IQ.  This
22811988Sandreas.sandberg@arm.com// is needed in case a long chain of such instructions occurs.
22911988Sandreas.sandberg@arm.comtemplate <class Impl>
23011988Sandreas.sandberg@arm.comvoid
23111988Sandreas.sandberg@arm.comInstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
23211988Sandreas.sandberg@arm.com{
23311988Sandreas.sandberg@arm.com    // Make sure the instruction is valid
23411988Sandreas.sandberg@arm.com    assert(inst);
23511988Sandreas.sandberg@arm.com
23611988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
23711988Sandreas.sandberg@arm.com            inst->readPC());
23811988Sandreas.sandberg@arm.com
23911988Sandreas.sandberg@arm.com    // Check if there are any free entries.  Panic if there are none.
24011988Sandreas.sandberg@arm.com    // Might want to have this return a fault in the future instead of
24111988Sandreas.sandberg@arm.com    // panicing.
24211988Sandreas.sandberg@arm.com    assert(freeEntries != 0);
24311988Sandreas.sandberg@arm.com
24412011Sgabeblack@google.com    // If the IQ currently has nothing in it, then there's a possibility
24511988Sandreas.sandberg@arm.com    // that the tail iterator is invalid (might have been pointing at an
24611988Sandreas.sandberg@arm.com    // instruction that was retired).  Reset the tail iterator.
24711988Sandreas.sandberg@arm.com    if (freeEntries == numEntries) {
24811988Sandreas.sandberg@arm.com        tail = cpu->instList.begin();
24911988Sandreas.sandberg@arm.com    }
25011988Sandreas.sandberg@arm.com
25111988Sandreas.sandberg@arm.com    // Move the tail iterator.  Instructions may not have been issued
25211988Sandreas.sandberg@arm.com    // to the IQ, so we may have to increment the iterator more than once.
25311988Sandreas.sandberg@arm.com    while ((*tail) != inst) {
25411988Sandreas.sandberg@arm.com        tail++;
25511988Sandreas.sandberg@arm.com
25611988Sandreas.sandberg@arm.com        // Make sure the tail iterator points at something legal.
25711988Sandreas.sandberg@arm.com        assert(tail != cpu->instList.end());
25811988Sandreas.sandberg@arm.com    }
25911988Sandreas.sandberg@arm.com
26011988Sandreas.sandberg@arm.com    assert(freeEntries <= numEntries);
26111988Sandreas.sandberg@arm.com
26211988Sandreas.sandberg@arm.com    // Have this instruction set itself as the producer of its destination
26311988Sandreas.sandberg@arm.com    // register(s).
26411988Sandreas.sandberg@arm.com    createDependency(inst);
26511988Sandreas.sandberg@arm.com}
26611988Sandreas.sandberg@arm.com
26711988Sandreas.sandberg@arm.com// Need to make sure the number of float and integer instructions
26811988Sandreas.sandberg@arm.com// issued does not exceed the total issue bandwidth.
26911988Sandreas.sandberg@arm.com// @todo: Figure out a better way to remove the squashed items from the
27011988Sandreas.sandberg@arm.com// lists.  Checking the top item of each list to see if it's squashed
27111988Sandreas.sandberg@arm.com// wastes time and forces jumps.
27211988Sandreas.sandberg@arm.comtemplate <class Impl>
27311988Sandreas.sandberg@arm.comvoid
27411988Sandreas.sandberg@arm.comInstructionQueue<Impl>::scheduleReadyInsts()
27511988Sandreas.sandberg@arm.com{
27611988Sandreas.sandberg@arm.com    DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
27711988Sandreas.sandberg@arm.com                "the IQ.\n");
27811988Sandreas.sandberg@arm.com
27911988Sandreas.sandberg@arm.com    int int_issued = 0;
28011988Sandreas.sandberg@arm.com    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