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