2c2
< * Copyright (c) 2004-2006 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2005 The Regents of The University of Michigan
26a27,28
> *
> * Authors: Kevin Lim
28a31,38
> // Todo:
> // Current ordering allows for 0 cycle added-to-scheduled. Could maybe fake
> // it; either do in reverse order, or have added instructions put into a
> // different ready queue that, in scheduleRreadyInsts(), gets put onto the
> // normal ready queue. This would however give only a one cycle delay,
> // but probably is more flexible to actually add in a delay parameter than
> // just running it backwards.
>
34d43
< #include "cpu/o3/fu_pool.hh"
37c46,48
< using namespace std;
---
> // Either compile error or max int due to sign extension.
> // Hack to avoid compile warnings.
> const InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max();
40,44c51,61
< InstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst,
< int fu_idx,
< InstructionQueue<Impl> *iq_ptr)
< : Event(&mainEventQueue, Stat_Event_Pri),
< inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false)
---
> InstructionQueue<Impl>::InstructionQueue(Params &params)
> : memDepUnit(params),
> numEntries(params.numIQEntries),
> intWidth(params.executeIntWidth),
> floatWidth(params.executeFloatWidth),
> branchWidth(params.executeBranchWidth),
> memoryWidth(params.executeMemoryWidth),
> totalWidth(params.issueWidth),
> numPhysIntRegs(params.numPhysIntRegs),
> numPhysFloatRegs(params.numPhysFloatRegs),
> commitToIEWDelay(params.commitToIEWDelay)
46,47c63,64
< this->setFlags(Event::AutoDelete);
< }
---
> // Initialize the number of free IQ entries.
> freeEntries = numEntries;
49,80d65
< template <class Impl>
< void
< InstructionQueue<Impl>::FUCompletion::process()
< {
< iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1);
< inst = NULL;
< }
<
<
< template <class Impl>
< const char *
< InstructionQueue<Impl>::FUCompletion::description()
< {
< return "Functional unit completion event";
< }
<
< template <class Impl>
< InstructionQueue<Impl>::InstructionQueue(Params *params)
< : dcacheInterface(params->dcacheInterface),
< fuPool(params->fuPool),
< numEntries(params->numIQEntries),
< totalWidth(params->issueWidth),
< numPhysIntRegs(params->numPhysIntRegs),
< numPhysFloatRegs(params->numPhysFloatRegs),
< commitToIEWDelay(params->commitToIEWDelay)
< {
< assert(fuPool);
<
< switchedOut = false;
<
< numThreads = params->numberOfThreads;
<
84c69
< DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs);
---
> DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs);
88c73
< dependGraph.resize(numPhysRegs);
---
> dependGraph = new DependencyEntry[numPhysRegs];
93,96c78,89
< //Initialize Mem Dependence Units
< for (int i = 0; i < numThreads; i++) {
< memDepUnit[i].init(params,i);
< memDepUnit[i].setIQ(this);
---
> // Initialize all the head pointers to point to NULL, and all the
> // entries as unready.
> // Note that in actuality, the registers corresponding to the logical
> // registers start off as ready. However this doesn't matter for the
> // IQ as the instruction should have been correctly told if those
> // registers are ready in rename. Thus it can all be initialized as
> // unready.
> for (int i = 0; i < numPhysRegs; ++i)
> {
> dependGraph[i].next = NULL;
> dependGraph[i].inst = NULL;
> regScoreboard[i] = false;
99,147d91
< resetState();
<
< string policy = params->smtIQPolicy;
<
< //Convert string to lowercase
< std::transform(policy.begin(), policy.end(), policy.begin(),
< (int(*)(int)) tolower);
<
< //Figure out resource sharing policy
< if (policy == "dynamic") {
< iqPolicy = Dynamic;
<
< //Set Max Entries to Total ROB Capacity
< for (int i = 0; i < numThreads; i++) {
< maxEntries[i] = numEntries;
< }
<
< } else if (policy == "partitioned") {
< iqPolicy = Partitioned;
<
< //@todo:make work if part_amt doesnt divide evenly.
< int part_amt = numEntries / numThreads;
<
< //Divide ROB up evenly
< for (int i = 0; i < numThreads; i++) {
< maxEntries[i] = part_amt;
< }
<
< DPRINTF(Fetch, "IQ sharing policy set to Partitioned:"
< "%i entries per thread.\n",part_amt);
<
< } else if (policy == "threshold") {
< iqPolicy = Threshold;
<
< double threshold = (double)params->smtIQThreshold / 100;
<
< int thresholdIQ = (int)((double)threshold * numEntries);
<
< //Divide up by threshold amount
< for (int i = 0; i < numThreads; i++) {
< maxEntries[i] = thresholdIQ;
< }
<
< DPRINTF(Fetch, "IQ sharing policy set to Threshold:"
< "%i entries per thread.\n",thresholdIQ);
< } else {
< assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic,"
< "Partitioned, Threshold}");
< }
151,165d94
< InstructionQueue<Impl>::~InstructionQueue()
< {
< dependGraph.reset();
< cprintf("Nodes traversed: %i, removed: %i\n",
< dependGraph.nodesTraversed, dependGraph.nodesRemoved);
< }
<
< template <class Impl>
< std::string
< InstructionQueue<Impl>::name() const
< {
< return cpu->name() + ".iq";
< }
<
< template <class Impl>
169d97
< using namespace Stats;
180,183c108
< iqInstsIssued
< .name(name() + ".iqInstsIssued")
< .desc("Number of instructions issued")
< .prereq(iqInstsIssued);
---
> // iqIntInstsAdded;
189a115,116
> // iqFloatInstsAdded;
>
194a122,123
> // iqBranchInstsAdded;
>
199a129,130
> // iqMemInstsAdded;
>
204a136,137
> // iqMiscInstsAdded;
>
214a148,153
> iqLoopSquashStalls
> .name(name() + ".iqLoopSquashStalls")
> .desc("Number of times issue loop had to restart due to squashed "
> "inst; mainly for profiling")
> .prereq(iqLoopSquashStalls);
>
232,332c171,172
< queueResDist
< .init(Num_OpClasses, 0, 99, 2)
< .name(name() + ".IQ:residence:")
< .desc("cycles from dispatch to issue")
< .flags(total | pdf | cdf )
< ;
< for (int i = 0; i < Num_OpClasses; ++i) {
< queueResDist.subname(i, opClassStrings[i]);
< }
< numIssuedDist
< .init(0,totalWidth,1)
< .name(name() + ".ISSUE:issued_per_cycle")
< .desc("Number of insts issued each cycle")
< .flags(pdf)
< ;
< /*
< dist_unissued
< .init(Num_OpClasses+2)
< .name(name() + ".ISSUE:unissued_cause")
< .desc("Reason ready instruction not issued")
< .flags(pdf | dist)
< ;
< for (int i=0; i < (Num_OpClasses + 2); ++i) {
< dist_unissued.subname(i, unissued_names[i]);
< }
< */
< statIssuedInstType
< .init(numThreads,Num_OpClasses)
< .name(name() + ".ISSUE:FU_type")
< .desc("Type of FU issued")
< .flags(total | pdf | dist)
< ;
< statIssuedInstType.ysubnames(opClassStrings);
<
< //
< // How long did instructions for a particular FU type wait prior to issue
< //
<
< issueDelayDist
< .init(Num_OpClasses,0,99,2)
< .name(name() + ".ISSUE:")
< .desc("cycles from operands ready to issue")
< .flags(pdf | cdf)
< ;
<
< for (int i=0; i<Num_OpClasses; ++i) {
< stringstream subname;
< subname << opClassStrings[i] << "_delay";
< issueDelayDist.subname(i, subname.str());
< }
<
< issueRate
< .name(name() + ".ISSUE:rate")
< .desc("Inst issue rate")
< .flags(total)
< ;
< issueRate = iqInstsIssued / cpu->numCycles;
< /*
< issue_stores
< .name(name() + ".ISSUE:stores")
< .desc("Number of stores issued")
< .flags(total)
< ;
< issue_stores = exe_refs - exe_loads;
< */
< /*
< issue_op_rate
< .name(name() + ".ISSUE:op_rate")
< .desc("Operation issue rate")
< .flags(total)
< ;
< issue_op_rate = issued_ops / numCycles;
< */
< statFuBusy
< .init(Num_OpClasses)
< .name(name() + ".ISSUE:fu_full")
< .desc("attempts to use FU when none available")
< .flags(pdf | dist)
< ;
< for (int i=0; i < Num_OpClasses; ++i) {
< statFuBusy.subname(i, opClassStrings[i]);
< }
<
< fuBusy
< .init(numThreads)
< .name(name() + ".ISSUE:fu_busy_cnt")
< .desc("FU busy when requested")
< .flags(total)
< ;
<
< fuBusyRate
< .name(name() + ".ISSUE:fu_busy_rate")
< .desc("FU busy rate (busy events/executed inst)")
< .flags(total)
< ;
< fuBusyRate = fuBusy / iqInstsIssued;
<
< for ( int i=0; i < numThreads; i++) {
< // Tell mem dependence unit to reg stats as well.
< memDepUnit[i].regStats();
< }
---
> // Tell mem dependence unit to reg stats as well.
> memDepUnit.regStats();
337c177
< InstructionQueue<Impl>::resetState()
---
> InstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr)
339,343c179
< //Initialize thread IQ counts
< for (int i = 0; i <numThreads; i++) {
< count[i] = 0;
< instList[i].clear();
< }
---
> cpu = cpu_ptr;
345,368c181
< // Initialize the number of free IQ entries.
< freeEntries = numEntries;
<
< // Note that in actuality, the registers corresponding to the logical
< // registers start off as ready. However this doesn't matter for the
< // IQ as the instruction should have been correctly told if those
< // registers are ready in rename. Thus it can all be initialized as
< // unready.
< for (int i = 0; i < numPhysRegs; ++i) {
< regScoreboard[i] = false;
< }
<
< for (int i = 0; i < numThreads; ++i) {
< squashedSeqNum[i] = 0;
< }
<
< for (int i = 0; i < Num_OpClasses; ++i) {
< while (!readyInsts[i].empty())
< readyInsts[i].pop();
< queueOnList[i] = false;
< readyIt[i] = listOrder.end();
< }
< nonSpecInsts.clear();
< listOrder.clear();
---
> tail = cpu->instList.begin();
373c186,187
< InstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr)
---
> InstructionQueue<Impl>::setIssueToExecuteQueue(
> TimeBuffer<IssueStruct> *i2e_ptr)
375,383c189
< DPRINTF(IQ, "Setting active threads list pointer.\n");
< activeThreads = at_ptr;
< }
<
< template <class Impl>
< void
< InstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr)
< {
< DPRINTF(IQ, "Set the issue to execute queue.\n");
---
> DPRINTF(IQ, "IQ: Set the issue to execute queue.\n");
391c197
< DPRINTF(IQ, "Set the time buffer.\n");
---
> DPRINTF(IQ, "IQ: Set the time buffer.\n");
398,448d203
< void
< InstructionQueue<Impl>::switchOut()
< {
< resetState();
< dependGraph.reset();
< switchedOut = true;
< for (int i = 0; i < numThreads; ++i) {
< memDepUnit[i].switchOut();
< }
< }
<
< template <class Impl>
< void
< InstructionQueue<Impl>::takeOverFrom()
< {
< switchedOut = false;
< }
<
< template <class Impl>
< int
< InstructionQueue<Impl>::entryAmount(int num_threads)
< {
< if (iqPolicy == Partitioned) {
< return numEntries / num_threads;
< } else {
< return 0;
< }
< }
<
<
< template <class Impl>
< void
< InstructionQueue<Impl>::resetEntries()
< {
< if (iqPolicy != Dynamic || numThreads > 1) {
< int active_threads = (*activeThreads).size();
<
< list<unsigned>::iterator threads = (*activeThreads).begin();
< list<unsigned>::iterator list_end = (*activeThreads).end();
<
< while (threads != list_end) {
< if (iqPolicy == Partitioned) {
< maxEntries[*threads++] = numEntries / active_threads;
< } else if(iqPolicy == Threshold && active_threads == 1) {
< maxEntries[*threads++] = numEntries;
< }
< }
< }
< }
<
< template <class Impl>
455,461d209
< template <class Impl>
< unsigned
< InstructionQueue<Impl>::numFreeEntries(unsigned tid)
< {
< return maxEntries[tid] - count[tid];
< }
<
476,503d223
< bool
< InstructionQueue<Impl>::isFull(unsigned tid)
< {
< if (numFreeEntries(tid) == 0) {
< return(true);
< } else {
< return(false);
< }
< }
<
< template <class Impl>
< bool
< InstructionQueue<Impl>::hasReadyInsts()
< {
< if (!listOrder.empty()) {
< return true;
< }
<
< for (int i = 0; i < Num_OpClasses; ++i) {
< if (!readyInsts[i].empty()) {
< return true;
< }
< }
<
< return false;
< }
<
< template <class Impl>
510,511c230,231
< DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n",
< new_inst->seqNum, new_inst->readPC());
---
> DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
> new_inst->readPC());
512a233,235
> // Check if there are any free entries. Panic if there are none.
> // Might want to have this return a fault in the future instead of
> // panicing.
515c238,243
< instList[new_inst->threadNumber].push_back(new_inst);
---
> // If the IQ currently has nothing in it, then there's a possibility
> // that the tail iterator is invalid (might have been pointing at an
> // instruction that was retired). Reset the tail iterator.
> if (freeEntries == numEntries) {
> tail = cpu->instList.begin();
> }
517c245,248
< --freeEntries;
---
> // Move the tail iterator. Instructions may not have been issued
> // to the IQ, so we may have to increment the iterator more than once.
> while ((*tail) != new_inst) {
> tail++;
519c250,252
< new_inst->setInIQ();
---
> // Make sure the tail iterator points at something legal.
> assert(tail != cpu->instList.end());
> }
520a254,257
>
> // Decrease the number of free entries.
> --freeEntries;
>
527c264
< addToProducers(new_inst);
---
> createDependency(new_inst);
528a266,267
> // If it's a memory instruction, add it to the memory dependency
> // unit.
530c269,271
< memDepUnit[new_inst->threadNumber].insert(new_inst);
---
> memDepUnit.insert(new_inst);
> // Uh..forgot to look it up and put it on the proper dependency list
> // if the instruction should not go yet.
531a273
> // If the instruction is ready then add it to the ready list.
537,538d278
< count[new_inst->threadNumber]++;
<
544c284
< InstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst)
---
> InstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst)
545a286,287
> nonSpecInsts[inst->seqNum] = inst;
>
549c291,292
< assert(new_inst);
---
> // Make sure the instruction is valid
> assert(inst);
551c294,295
< nonSpecInsts[new_inst->seqNum] = new_inst;
---
> DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
> inst->readPC());
553,556c297,299
< DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x "
< "to the IQ.\n",
< new_inst->seqNum, new_inst->readPC());
<
---
> // Check if there are any free entries. Panic if there are none.
> // Might want to have this return a fault in the future instead of
> // panicing.
559c302,307
< instList[new_inst->threadNumber].push_back(new_inst);
---
> // If the IQ currently has nothing in it, then there's a possibility
> // that the tail iterator is invalid (might have been pointing at an
> // instruction that was retired). Reset the tail iterator.
> if (freeEntries == numEntries) {
> tail = cpu->instList.begin();
> }
561c309,312
< --freeEntries;
---
> // Move the tail iterator. Instructions may not have been issued
> // to the IQ, so we may have to increment the iterator more than once.
> while ((*tail) != inst) {
> tail++;
563c314,316
< new_inst->setInIQ();
---
> // Make sure the tail iterator points at something legal.
> assert(tail != cpu->instList.end());
> }
564a318,320
> // Decrease the number of free entries.
> --freeEntries;
>
567c323
< addToProducers(new_inst);
---
> createDependency(inst);
571,572c327,328
< if (new_inst->isMemRef()) {
< memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst);
---
> if (inst->isMemRef()) {
> memDepUnit.insertNonSpec(inst);
576,579d331
<
< count[new_inst->threadNumber]++;
<
< assert(freeEntries == (numEntries - countInsts()));
581a334,337
> // Slightly hack function to advance the tail iterator in the case that
> // the IEW stage issues an instruction that is not added to the IQ. This
> // is needed in case a long chain of such instructions occurs.
> // I don't think this is used anymore.
584c340
< InstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst)
---
> InstructionQueue<Impl>::advanceTail(DynInstPtr &inst)
586c342,343
< memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst);
---
> // Make sure the instruction is valid
> assert(inst);
588,589c345,346
< insertNonSpec(barr_inst);
< }
---
> DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n",
> inst->readPC());
591,598c348,373
< template <class Impl>
< typename Impl::DynInstPtr
< InstructionQueue<Impl>::getInstToExecute()
< {
< assert(!instsToExecute.empty());
< DynInstPtr inst = instsToExecute.front();
< instsToExecute.pop_front();
< return inst;
---
> // Check if there are any free entries. Panic if there are none.
> // Might want to have this return a fault in the future instead of
> // panicing.
> assert(freeEntries != 0);
>
> // If the IQ currently has nothing in it, then there's a possibility
> // that the tail iterator is invalid (might have been pointing at an
> // instruction that was retired). Reset the tail iterator.
> if (freeEntries == numEntries) {
> tail = cpu->instList.begin();
> }
>
> // Move the tail iterator. Instructions may not have been issued
> // to the IQ, so we may have to increment the iterator more than once.
> while ((*tail) != inst) {
> tail++;
>
> // Make sure the tail iterator points at something legal.
> assert(tail != cpu->instList.end());
> }
>
> assert(freeEntries <= numEntries);
>
> // Have this instruction set itself as the producer of its destination
> // register(s).
> createDependency(inst);
600a376,380
> // Need to make sure the number of float and integer instructions
> // issued does not exceed the total issue bandwidth.
> // @todo: Figure out a better way to remove the squashed items from the
> // lists. Checking the top item of each list to see if it's squashed
> // wastes time and forces jumps.
603c383
< InstructionQueue<Impl>::addToOrderList(OpClass op_class)
---
> InstructionQueue<Impl>::scheduleReadyInsts()
605c385,386
< assert(!readyInsts[op_class].empty());
---
> DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from "
> "the IQ.\n");
607c388,393
< ListOrderEntry queue_entry;
---
> int int_issued = 0;
> int float_issued = 0;
> int branch_issued = 0;
> int memory_issued = 0;
> int squashed_issued = 0;
> int total_issued = 0;
609c395
< queue_entry.queueType = op_class;
---
> IssueStruct *i2e_info = issueToExecuteQueue->access(0);
611c397,402
< queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
---
> bool insts_available = !readyBranchInsts.empty() ||
> !readyIntInsts.empty() ||
> !readyFloatInsts.empty() ||
> !memDepUnit.empty() ||
> !readyMiscInsts.empty() ||
> !squashedInsts.empty();
613,614c404,406
< ListOrderIt list_it = listOrder.begin();
< ListOrderIt list_end_it = listOrder.end();
---
> // Note: Requires a globally defined constant.
> InstSeqNum oldest_inst = MaxInstSeqNum;
> InstList list_with_oldest = None;
616,619c408,414
< while (list_it != list_end_it) {
< if ((*list_it).oldestInst > queue_entry.oldestInst) {
< break;
< }
---
> // Temporary values.
> DynInstPtr int_head_inst;
> DynInstPtr float_head_inst;
> DynInstPtr branch_head_inst;
> DynInstPtr mem_head_inst;
> DynInstPtr misc_head_inst;
> DynInstPtr squashed_head_inst;
621,622c416,424
< list_it++;
< }
---
> // Somewhat nasty code to look at all of the lists where issuable
> // instructions are located, and choose the oldest instruction among
> // those lists. Consider a rewrite in the future.
> while (insts_available && total_issued < totalWidth)
> {
> // Set this to false. Each if-block is required to set it to true
> // if there were instructions available this check. This will cause
> // this loop to run once more than necessary, but avoids extra calls.
> insts_available = false;
624,626c426
< readyIt[op_class] = listOrder.insert(list_it, queue_entry);
< queueOnList[op_class] = true;
< }
---
> oldest_inst = MaxInstSeqNum;
628,639c428
< template <class Impl>
< void
< InstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it)
< {
< // Get iterator of next item on the list
< // Delete the original iterator
< // Determine if the next item is either the end of the list or younger
< // than the new instruction. If so, then add in a new iterator right here.
< // If not, then move along.
< ListOrderEntry queue_entry;
< OpClass op_class = (*list_order_it).queueType;
< ListOrderIt next_it = list_order_it;
---
> list_with_oldest = None;
641c430,431
< ++next_it;
---
> if (!readyIntInsts.empty() &&
> int_issued < intWidth) {
643,644c433
< queue_entry.queueType = op_class;
< queue_entry.oldestInst = readyInsts[op_class].top()->seqNum;
---
> insts_available = true;
646,649c435
< while (next_it != listOrder.end() &&
< (*next_it).oldestInst < queue_entry.oldestInst) {
< ++next_it;
< }
---
> int_head_inst = readyIntInsts.top();
651,652c437,438
< readyIt[op_class] = listOrder.insert(next_it, queue_entry);
< }
---
> if (int_head_inst->isSquashed()) {
> readyIntInsts.pop();
654,662c440
< template <class Impl>
< void
< InstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx)
< {
< // The CPU could have been sleeping until this op completed (*extremely*
< // long latency op). Wake it if it was. This may be overkill.
< if (isSwitchedOut()) {
< return;
< }
---
> ++iqLoopSquashStalls;
664c442,443
< iewStage->wakeCPU();
---
> continue;
> }
666,667c445
< if (fu_idx > -1)
< fuPool->freeUnitNextCycle(fu_idx);
---
> oldest_inst = int_head_inst->seqNum;
669,677c447,448
< // @todo: Ensure that these FU Completions happen at the beginning
< // of a cycle, otherwise they could add too many instructions to
< // the queue.
< // @todo: This could break if there's multiple multi-cycle ops
< // finishing on this cycle. Maybe implement something like
< // instToCommit in iew_impl.hh.
< issueToExecuteQueue->access(0)->size++;
< instsToExecute.push_back(inst);
< // int &size = issueToExecuteQueue->access(0)->size;
---
> list_with_oldest = Int;
> }
679,680c450,451
< // issueToExecuteQueue->access(0)->insts[size++] = inst;
< }
---
> if (!readyFloatInsts.empty() &&
> float_issued < floatWidth) {
682,690c453
< // @todo: Figure out a better way to remove the squashed items from the
< // lists. Checking the top item of each list to see if it's squashed
< // wastes time and forces jumps.
< template <class Impl>
< void
< InstructionQueue<Impl>::scheduleReadyInsts()
< {
< DPRINTF(IQ, "Attempting to schedule ready instructions from "
< "the IQ.\n");
---
> insts_available = true;
692c455
< IssueStruct *i2e_info = issueToExecuteQueue->access(0);
---
> float_head_inst = readyFloatInsts.top();
694,704c457,458
< // Have iterator to head of the list
< // While I haven't exceeded bandwidth or reached the end of the list,
< // Try to get a FU that can do what this op needs.
< // If successful, change the oldestInst to the new top of the list, put
< // the queue in the proper place in the list.
< // Increment the iterator.
< // This will avoid trying to schedule a certain op class if there are no
< // FUs that handle it.
< ListOrderIt order_it = listOrder.begin();
< ListOrderIt order_end_it = listOrder.end();
< int total_issued = 0;
---
> if (float_head_inst->isSquashed()) {
> readyFloatInsts.pop();
706,708c460
< while (total_issued < totalWidth &&
< order_it != order_end_it) {
< OpClass op_class = (*order_it).queueType;
---
> ++iqLoopSquashStalls;
710c462,464
< assert(!readyInsts[op_class].empty());
---
> continue;
> } else if (float_head_inst->seqNum < oldest_inst) {
> oldest_inst = float_head_inst->seqNum;
712c466,468
< DynInstPtr issuing_inst = readyInsts[op_class].top();
---
> list_with_oldest = Float;
> }
> }
714c470,471
< assert(issuing_inst->seqNum == (*order_it).oldestInst);
---
> if (!readyBranchInsts.empty() &&
> branch_issued < branchWidth) {
716,717c473
< if (issuing_inst->isSquashed()) {
< readyInsts[op_class].pop();
---
> insts_available = true;
719,724c475
< if (!readyInsts[op_class].empty()) {
< moveToYoungerInst(order_it);
< } else {
< readyIt[op_class] = listOrder.end();
< queueOnList[op_class] = false;
< }
---
> branch_head_inst = readyBranchInsts.top();
726c477,478
< listOrder.erase(order_it++);
---
> if (branch_head_inst->isSquashed()) {
> readyBranchInsts.pop();
728c480
< ++iqSquashedInstsIssued;
---
> ++iqLoopSquashStalls;
730c482,488
< continue;
---
> continue;
> } else if (branch_head_inst->seqNum < oldest_inst) {
> oldest_inst = branch_head_inst->seqNum;
>
> list_with_oldest = Branch;
> }
>
733,735c491,492
< int idx = -2;
< int op_latency = 1;
< int tid = issuing_inst->threadNumber;
---
> if (!memDepUnit.empty() &&
> memory_issued < memoryWidth) {
737,738c494
< if (op_class != No_OpClass) {
< idx = fuPool->getUnit(op_class);
---
> insts_available = true;
740,741c496,507
< if (idx > -1) {
< op_latency = fuPool->getOpLatency(op_class);
---
> mem_head_inst = memDepUnit.top();
>
> if (mem_head_inst->isSquashed()) {
> memDepUnit.pop();
>
> ++iqLoopSquashStalls;
>
> continue;
> } else if (mem_head_inst->seqNum < oldest_inst) {
> oldest_inst = mem_head_inst->seqNum;
>
> list_with_oldest = Memory;
745,749c511
< if (idx == -2 || idx != -1) {
< if (op_latency == 1) {
< // i2e_info->insts[exec_queue_slot++] = issuing_inst;
< i2e_info->size++;
< instsToExecute.push_back(issuing_inst);
---
> if (!readyMiscInsts.empty()) {
751,759c513
< // Add the FU onto the list of FU's to be freed next
< // cycle if we used one.
< if (idx >= 0)
< fuPool->freeUnitNextCycle(idx);
< } else {
< int issue_latency = fuPool->getIssueLatency(op_class);
< // Generate completion event for the FU
< FUCompletion *execution = new FUCompletion(issuing_inst,
< idx, this);
---
> insts_available = true;
761c515
< execution->schedule(curTick + cpu->cycles(issue_latency - 1));
---
> misc_head_inst = readyMiscInsts.top();
763,771c517,518
< // @todo: Enforce that issue_latency == 1 or op_latency
< if (issue_latency > 1) {
< execution->setFreeFU();
< } else {
< // @todo: Not sure I'm accounting for the
< // multi-cycle op in a pipelined FU properly, or
< // the number of instructions issued in one cycle.
< // i2e_info->insts[exec_queue_slot++] = issuing_inst;
< // i2e_info->size++;
---
> if (misc_head_inst->isSquashed()) {
> readyMiscInsts.pop();
773,775c520,526
< // Add the FU onto the list of FU's to be freed next cycle.
< fuPool->freeUnitNextCycle(idx);
< }
---
> ++iqLoopSquashStalls;
>
> continue;
> } else if (misc_head_inst->seqNum < oldest_inst) {
> oldest_inst = misc_head_inst->seqNum;
>
> list_with_oldest = Misc;
776a528
> }
778,781c530
< DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x "
< "[sn:%lli]\n",
< tid, issuing_inst->readPC(),
< issuing_inst->seqNum);
---
> if (!squashedInsts.empty()) {
783c532
< readyInsts[op_class].pop();
---
> insts_available = true;
785,789c534,537
< if (!readyInsts[op_class].empty()) {
< moveToYoungerInst(order_it);
< } else {
< readyIt[op_class] = listOrder.end();
< queueOnList[op_class] = false;
---
> squashed_head_inst = squashedInsts.top();
>
> if (squashed_head_inst->seqNum < oldest_inst) {
> list_with_oldest = Squashed;
792,793c540
< issuing_inst->setIssued();
< ++total_issued;
---
> }
795,803c542
< if (!issuing_inst->isMemRef()) {
< // Memory instructions can not be freed from the IQ until they
< // complete.
< ++freeEntries;
< count[tid]--;
< issuing_inst->removeInIQ();
< } else {
< memDepUnit[tid].issue(issuing_inst);
< }
---
> DynInstPtr issuing_inst = NULL;
805,810c544,603
< listOrder.erase(order_it++);
< statIssuedInstType[tid][op_class]++;
< } else {
< statFuBusy[op_class]++;
< fuBusy[tid]++;
< ++order_it;
---
> switch (list_with_oldest) {
> case None:
> DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing "
> "inst is %#x.\n", issuing_inst);
> break;
>
> case Int:
> issuing_inst = int_head_inst;
> readyIntInsts.pop();
> ++int_issued;
> DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n",
> issuing_inst->readPC());
> break;
>
> case Float:
> issuing_inst = float_head_inst;
> readyFloatInsts.pop();
> ++float_issued;
> DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n",
> issuing_inst->readPC());
> break;
>
> case Branch:
> issuing_inst = branch_head_inst;
> readyBranchInsts.pop();
> ++branch_issued;
> DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n",
> issuing_inst->readPC());
> break;
>
> case Memory:
> issuing_inst = mem_head_inst;
>
> memDepUnit.pop();
> ++memory_issued;
> DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n",
> issuing_inst->readPC());
> break;
>
> case Misc:
> issuing_inst = misc_head_inst;
> readyMiscInsts.pop();
>
> ++iqMiscInstsIssued;
>
> DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n",
> issuing_inst->readPC());
> break;
>
> case Squashed:
> assert(0 && "Squashed insts should not issue any more!");
> squashedInsts.pop();
> // Set the squashed instruction as able to commit so that commit
> // can just drop it from the ROB. This is a bit faked.
> ++squashed_issued;
> ++freeEntries;
>
> DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n",
> squashed_head_inst->readPC());
> break;
812d604
< }
814,815c606,608
< numIssuedDist.sample(total_issued);
< iqInstsIssued+= total_issued;
---
> if (list_with_oldest != None && list_with_oldest != Squashed) {
> i2e_info->insts[total_issued] = issuing_inst;
> i2e_info->size++;
817,820c610,616
< if (total_issued) {
< cpu->activityThisCycle();
< } else {
< DPRINTF(IQ, "Not able to schedule any instructions.\n");
---
> issuing_inst->setIssued();
>
> ++freeEntries;
> ++total_issued;
> }
>
> assert(freeEntries == (numEntries - countInsts()));
821a618,623
>
> iqIntInstsIssued += int_issued;
> iqFloatInstsIssued += float_issued;
> iqBranchInstsIssued += branch_issued;
> iqMemInstsIssued += memory_issued;
> iqSquashedInstsIssued += squashed_issued;
828,829c630,631
< DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready "
< "to execute.\n", inst);
---
> DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence "
> "number %i as ready to execute.\n", inst);
831c633
< NonSpecMapIt inst_it = nonSpecInsts.find(inst);
---
> non_spec_it_t inst_it = nonSpecInsts.find(inst);
835,836c637
< unsigned tid = (*inst_it).second->threadNumber;
<
---
> // Mark this instruction as ready to issue.
838a640
> // Now schedule the instruction.
842c644
< memDepUnit[tid].nonSpecInstReady((*inst_it).second);
---
> memDepUnit.nonSpecInstReady((*inst_it).second);
845,846d646
< (*inst_it).second = NULL;
<
852,869d651
< InstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid)
< {
< DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n",
< tid,inst);
<
< ListIt iq_it = instList[tid].begin();
<
< while (iq_it != instList[tid].end() &&
< (*iq_it)->seqNum <= inst) {
< ++iq_it;
< instList[tid].pop_front();
< }
<
< assert(freeEntries == (numEntries - countInsts()));
< }
<
< template <class Impl>
< int
872c654,658
< int dependents = 0;
---
> DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n");
> //Look at the physical destination register of the DynInst
> //and look it up on the dependency graph. Then mark as ready
> //any instructions within the instruction queue.
> DependencyEntry *curr;
874,877d659
< DPRINTF(IQ, "Waking dependents of completed instruction.\n");
<
< assert(!completed_inst->isSquashed());
<
879,883c661,662
< // instruction if it is a memory instruction. Also complete the memory
< // instruction at this point since we know it executed without issues.
< // @todo: Might want to rename "completeMemInst" to something that
< // indicates that it won't need to be replayed, and call this
< // earlier. Might not be a big deal.
---
> // instruction if it is a memory instruction.
>
885,889c664
< memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst);
< completeMemInst(completed_inst);
< } else if (completed_inst->isMemBarrier() ||
< completed_inst->isWriteBarrier()) {
< memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst);
---
> memDepUnit.wakeDependents(completed_inst);
906c681
< DPRINTF(IQ, "Waking any dependents on register %i.\n",
---
> DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n",
909,911c684,687
< //Go through the dependency chain, marking the registers as
< //ready within the waiting instructions.
< DynInstPtr dep_inst = dependGraph.pop(dest_reg);
---
> //Maybe abstract this part into a function.
> //Go through the dependency chain, marking the registers as ready
> //within the waiting instructions.
> while (dependGraph[dest_reg].next) {
913,915c689
< while (dep_inst) {
< DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n",
< dep_inst->readPC());
---
> curr = dependGraph[dest_reg].next;
916a691,693
> DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n",
> curr->inst->readPC());
>
918,921c695,698
< // so that it knows which of its source registers is
< // ready. However that would mean that the dependency
< // graph entries would need to hold the src_reg_idx.
< dep_inst->markSrcRegReady();
---
> // so that it knows which of its source registers is ready.
> // However that would mean that the dependency graph entries
> // would need to hold the src_reg_idx.
> curr->inst->markSrcRegReady();
923c700
< addIfReady(dep_inst);
---
> addIfReady(curr->inst);
925c702
< dep_inst = dependGraph.pop(dest_reg);
---
> dependGraph[dest_reg].next = curr->next;
927c704,708
< ++dependents;
---
> DependencyEntry::mem_alloc_counter--;
>
> curr->inst = NULL;
>
> delete curr;
930,933c711,714
< // Reset the head node now that all of its dependents have
< // been woken up.
< assert(dependGraph.empty(dest_reg));
< dependGraph.clearInst(dest_reg);
---
> // Reset the head node now that all of its dependents have been woken
> // up.
> dependGraph[dest_reg].next = NULL;
> dependGraph[dest_reg].inst = NULL;
938d718
< return dependents;
943,997d722
< InstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst)
< {
< OpClass op_class = ready_inst->opClass();
<
< readyInsts[op_class].push(ready_inst);
<
< // Will need to reorder the list if either a queue is not on the list,
< // or it has an older instruction than last time.
< if (!queueOnList[op_class]) {
< addToOrderList(op_class);
< } else if (readyInsts[op_class].top()->seqNum <
< (*readyIt[op_class]).oldestInst) {
< listOrder.erase(readyIt[op_class]);
< addToOrderList(op_class);
< }
<
< DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
< "the ready list, PC %#x opclass:%i [sn:%lli].\n",
< ready_inst->readPC(), op_class, ready_inst->seqNum);
< }
<
< template <class Impl>
< void
< InstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst)
< {
< memDepUnit[resched_inst->threadNumber].reschedule(resched_inst);
< }
<
< template <class Impl>
< void
< InstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst)
< {
< memDepUnit[replay_inst->threadNumber].replay(replay_inst);
< }
<
< template <class Impl>
< void
< InstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst)
< {
< int tid = completed_inst->threadNumber;
<
< DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n",
< completed_inst->readPC(), completed_inst->seqNum);
<
< ++freeEntries;
<
< completed_inst->memOpDone = true;
<
< memDepUnit[tid].completed(completed_inst);
<
< count[tid]--;
< }
<
< template <class Impl>
< void
1001c726
< memDepUnit[store->threadNumber].violation(store, faulting_load);
---
> memDepUnit.violation(store, faulting_load);
1006c731
< InstructionQueue<Impl>::squash(unsigned tid)
---
> InstructionQueue<Impl>::squash()
1008,1009c733
< DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in "
< "the IQ.\n", tid);
---
> DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n");
1013c737
< squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum;
---
> squashedSeqNum = fromCommit->commitInfo.doneSeqNum;
1014a739,741
> // Setup the squash iterator to point to the tail.
> squashIt = tail;
>
1016,1017c743,744
< if (count[tid] > 0) {
< doSquash(tid);
---
> if (freeEntries != numEntries) {
> doSquash();
1021c748
< memDepUnit[tid].squash(squashedSeqNum[tid], tid);
---
> memDepUnit.squash(squashedSeqNum);
1026c753
< InstructionQueue<Impl>::doSquash(unsigned tid)
---
> InstructionQueue<Impl>::doSquash()
1028,1030c755,758
< // Start at the tail.
< ListIt squash_it = instList[tid].end();
< --squash_it;
---
> // Make sure the squash iterator isn't pointing to nothing.
> assert(squashIt != cpu->instList.end());
> // Make sure the squashed sequence number is valid.
> assert(squashedSeqNum != 0);
1032,1033c760
< DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n",
< tid, squashedSeqNum[tid]);
---
> DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n");
1037,1038c764,765
< while (squash_it != instList[tid].end() &&
< (*squash_it)->seqNum > squashedSeqNum[tid]) {
---
> while ((*squashIt)->seqNum > squashedSeqNum) {
> DynInstPtr squashed_inst = (*squashIt);
1040,1041d766
< DynInstPtr squashed_inst = (*squash_it);
<
1044,1048c769,770
< if (squashed_inst->threadNumber != tid ||
< squashed_inst->isSquashedInIQ()) {
< --squash_it;
< continue;
< }
---
> if (!squashed_inst->isIssued() &&
> !squashed_inst->isSquashedInIQ()) {
1050,1053d771
< if (!squashed_inst->isIssued() ||
< (squashed_inst->isMemRef() &&
< !squashed_inst->memOpDone)) {
<
1055,1058c773,777
< if (!squashed_inst->isNonSpeculative() &&
< !squashed_inst->isStoreConditional() &&
< !squashed_inst->isMemBarrier() &&
< !squashed_inst->isWriteBarrier()) {
---
> // Hack for now: These below don't add themselves to the
> // dependency list, so don't try to remove them.
> if (!squashed_inst->isNonSpeculative()/* &&
> !squashed_inst->isStore()*/
> ) {
1067,1075c786,791
< // Only remove it from the dependency graph if it
< // was placed there in the first place.
<
< // Instead of doing a linked list traversal, we
< // can just remove these squashed instructions
< // either at issue time, or when the register is
< // overwritten. The only downside to this is it
< // leaves more room for error.
<
---
> // Only remove it from the dependency graph if it was
> // placed there in the first place.
> // HACK: This assumes that instructions woken up from the
> // dependency chain aren't informed that a specific src
> // register has become ready. This may not always be true
> // in the future.
1078c794
< dependGraph.remove(src_reg, squashed_inst);
---
> dependGraph[src_reg].remove(squashed_inst);
1081d796
<
1083a799,800
>
> // Might want to remove producers as well.
1085,1087c802
< NonSpecMapIt ns_inst_it =
< nonSpecInsts.find(squashed_inst->seqNum);
< assert(ns_inst_it != nonSpecInsts.end());
---
> nonSpecInsts[squashed_inst->seqNum] = NULL;
1089c804
< (*ns_inst_it).second = NULL;
---
> nonSpecInsts.erase(squashed_inst->seqNum);
1091,1092d805
< nonSpecInsts.erase(ns_inst_it);
<
1101,1102c814
< // @todo: Remove this hack where several statuses are set so the
< // inst will flow through the rest of the pipeline.
---
> // squashedInsts.push(squashed_inst);
1105d816
< squashed_inst->removeInIQ();
1107,1109d817
< //Update Thread IQ Count
< count[squashed_inst->threadNumber]--;
<
1112,1114c820,821
< DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x "
< "squashed.\n",
< tid, squashed_inst->seqNum, squashed_inst->readPC());
---
> DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n",
> squashed_inst->readPC());
1117c824
< instList[tid].erase(squash_it--);
---
> --squashIt;
1119a827,833
>
> assert(freeEntries <= numEntries);
>
> if (freeEntries == numEntries) {
> tail = cpu->instList.end();
> }
>
1122a837,901
> void
> InstructionQueue<Impl>::stopSquash()
> {
> // Clear up the squash variables to ensure that squashing doesn't
> // get called improperly.
> squashedSeqNum = 0;
>
> squashIt = cpu->instList.end();
> }
>
> template <class Impl>
> void
> InstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst)
> {
> //Add this new, dependent instruction at the head of the dependency
> //chain.
>
> // First create the entry that will be added to the head of the
> // dependency chain.
> DependencyEntry *new_entry = new DependencyEntry;
> new_entry->next = this->next;
> new_entry->inst = new_inst;
>
> // Then actually add it to the chain.
> this->next = new_entry;
>
> ++mem_alloc_counter;
> }
>
> template <class Impl>
> void
> InstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove)
> {
> DependencyEntry *prev = this;
> DependencyEntry *curr = this->next;
>
> // Make sure curr isn't NULL. Because this instruction is being
> // removed from a dependency list, it must have been placed there at
> // an earlier time. The dependency chain should not be empty,
> // unless the instruction dependent upon it is already ready.
> if (curr == NULL) {
> return;
> }
>
> // Find the instruction to remove within the dependency linked list.
> while(curr->inst != inst_to_remove)
> {
> prev = curr;
> curr = curr->next;
>
> assert(curr != NULL);
> }
>
> // Now remove this instruction from the list.
> prev->next = curr->next;
>
> --mem_alloc_counter;
>
> // Could push this off to the destructor of DependencyEntry
> curr->inst = NULL;
>
> delete curr;
> }
>
> template <class Impl>
1146c925
< DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
---
> DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
1150c929
< dependGraph.insert(src_reg, new_inst);
---
> dependGraph[src_reg].insert(new_inst);
1156c935
< DPRINTF(IQ, "Instruction PC %#x has src reg %i that "
---
> DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that "
1160c939
< new_inst->markSrcRegReady(src_reg_idx);
---
> new_inst->markSrcRegReady();
1170c949
< InstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst)
---
> InstructionQueue<Impl>::createDependency(DynInstPtr &new_inst)
1172,1175c951,954
< // Nothing really needs to be marked when an instruction becomes
< // the producer of a register's value, but for convenience a ptr
< // to the producing instruction will be placed in the head node of
< // the dependency links.
---
> //Actually nothing really needs to be marked when an
> //instruction becomes the producer of a register's value,
> //but for convenience a ptr to the producing instruction will
> //be placed in the head node of the dependency links.
1192,1194c971,975
< if (!dependGraph.empty(dest_reg)) {
< dependGraph.dump();
< panic("Dependency graph %i not empty!", dest_reg);
---
> dependGraph[dest_reg].inst = new_inst;
>
> if (dependGraph[dest_reg].next) {
> dumpDependGraph();
> panic("IQ: Dependency graph not empty!");
1197,1198d977
< dependGraph.setInst(dest_reg, new_inst);
<
1208c987
< // If the instruction now has all of its source registers
---
> //If the instruction now has all of its source registers
1213c992
< if (inst->isMemRef()) {
---
> if (inst->isControl()) {
1215c994,997
< DPRINTF(IQ, "Checking if memory instruction can issue.\n");
---
> DPRINTF(IQ, "IQ: Branch instruction is ready to issue, "
> "putting it onto the ready list, PC %#x.\n",
> inst->readPC());
> readyBranchInsts.push(inst);
1216a999,1002
> } else if (inst->isMemRef()) {
>
> DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n");
>
1219d1004
< memDepUnit[inst->threadNumber].regsReady(inst);
1221,1222c1006
< return;
< }
---
> memDepUnit.regsReady(inst);
1224c1008,1022
< OpClass op_class = inst->opClass();
---
> #if 0
> if (memDepUnit.readyToIssue(inst)) {
> DPRINTF(IQ, "IQ: Memory instruction is ready to issue, "
> "putting it onto the ready list, PC %#x.\n",
> inst->readPC());
> readyMemInsts.push(inst);
> } else {
> // Make dependent on the store.
> // Will need some way to get the store instruction it should
> // be dependent upon; then when the store issues it can
> // put the instruction on the ready list.
> // Yet another tree?
> assert(0 && "Instruction has no way to actually issue");
> }
> #endif
1226,1228c1024
< DPRINTF(IQ, "Instruction is ready to issue, putting it onto "
< "the ready list, PC %#x opclass:%i [sn:%lli].\n",
< inst->readPC(), op_class, inst->seqNum);
---
> } else if (inst->isInteger()) {
1230c1026,1029
< readyInsts[op_class].push(inst);
---
> DPRINTF(IQ, "IQ: Integer instruction is ready to issue, "
> "putting it onto the ready list, PC %#x.\n",
> inst->readPC());
> readyIntInsts.push(inst);
1232,1239c1031,1043
< // Will need to reorder the list if either a queue is not on the list,
< // or it has an older instruction than last time.
< if (!queueOnList[op_class]) {
< addToOrderList(op_class);
< } else if (readyInsts[op_class].top()->seqNum <
< (*readyIt[op_class]).oldestInst) {
< listOrder.erase(readyIt[op_class]);
< addToOrderList(op_class);
---
> } else if (inst->isFloating()) {
>
> DPRINTF(IQ, "IQ: Floating instruction is ready to issue, "
> "putting it onto the ready list, PC %#x.\n",
> inst->readPC());
> readyFloatInsts.push(inst);
>
> } else {
> DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, "
> "putting it onto the ready list, PC %#x..\n",
> inst->readPC());
>
> readyMiscInsts.push(inst);
1243a1048,1053
> /*
> * Caution, this function must not be called prior to tail being updated at
> * least once, otherwise it will fail the assertion. This is because
> * instList.begin() actually changes upon the insertion of an element into the
> * list when the list is empty.
> */
1248,1252c1058
< //ksewell:This works but definitely could use a cleaner write
< //with a more intuitive way of counting. Right now it's
< //just brute force ....
<
< #if 0
---
> ListIt count_it = cpu->instList.begin();
1255,1256c1061,1062
< for (int i = 0; i < numThreads; ++i) {
< ListIt count_it = instList[i].begin();
---
> if (tail == cpu->instList.end())
> return 0;
1258,1270c1064,1066
< while (count_it != instList[i].end()) {
< if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) {
< if (!(*count_it)->isIssued()) {
< ++total_insts;
< } else if ((*count_it)->isMemRef() &&
< !(*count_it)->memOpDone) {
< // Loads that have not been marked as executed still count
< // towards the total instructions.
< ++total_insts;
< }
< }
<
< ++count_it;
---
> while (count_it != tail) {
> if (!(*count_it)->isIssued()) {
> ++total_insts;
1271a1068,1071
>
> ++count_it;
>
> assert(count_it != cpu->instList.end());
1273a1074,1080
> // Need to count the tail iterator as well.
> if (count_it != cpu->instList.end() &&
> (*count_it) &&
> !(*count_it)->isIssued()) {
> ++total_insts;
> }
>
1275,1277d1081
< #else
< return numEntries - freeEntries;
< #endif
1282c1086
< InstructionQueue<Impl>::dumpLists()
---
> InstructionQueue<Impl>::dumpDependGraph()
1284,1285c1088
< for (int i = 0; i < Num_OpClasses; ++i) {
< cprintf("Ready list %i size: %i\n", i, readyInsts[i].size());
---
> DependencyEntry *curr;
1287,1288c1090,1092
< cprintf("\n");
< }
---
> for (int i = 0; i < numPhysRegs; ++i)
> {
> curr = &dependGraph[i];
1290c1094,1099
< cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
---
> if (curr->inst) {
> cprintf("dependGraph[%i]: producer: %#x consumer: ", i,
> curr->inst->readPC());
> } else {
> cprintf("dependGraph[%i]: No producer. consumer: ", i);
> }
1292,1293c1101,1102
< NonSpecMapIt non_spec_it = nonSpecInsts.begin();
< NonSpecMapIt non_spec_end_it = nonSpecInsts.end();
---
> while (curr->next != NULL) {
> curr = curr->next;
1295c1104,1105
< cprintf("Non speculative list: ");
---
> cprintf("%#x ", curr->inst->readPC());
> }
1297,1300c1107
< while (non_spec_it != non_spec_end_it) {
< cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(),
< (*non_spec_it).second->seqNum);
< ++non_spec_it;
---
> cprintf("\n");
1302,1319d1108
<
< cprintf("\n");
<
< ListOrderIt list_order_it = listOrder.begin();
< ListOrderIt list_order_end_it = listOrder.end();
< int i = 1;
<
< cprintf("List order: ");
<
< while (list_order_it != list_order_end_it) {
< cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType,
< (*list_order_it).oldestInst);
<
< ++list_order_it;
< ++i;
< }
<
< cprintf("\n");
1322d1110
<
1325c1113
< InstructionQueue<Impl>::dumpInsts()
---
> InstructionQueue<Impl>::dumpLists()
1327,1330c1115
< for (int i = 0; i < numThreads; ++i) {
< int num = 0;
< int valid_num = 0;
< ListIt inst_list_it = instList[i].begin();
---
> cprintf("Ready integer list size: %i\n", readyIntInsts.size());
1332,1347c1117
< while (inst_list_it != instList[i].end())
< {
< cprintf("Instruction:%i\n",
< num);
< if (!(*inst_list_it)->isSquashed()) {
< if (!(*inst_list_it)->isIssued()) {
< ++valid_num;
< cprintf("Count:%i\n", valid_num);
< } else if ((*inst_list_it)->isMemRef() &&
< !(*inst_list_it)->memOpDone) {
< // Loads that have not been marked as executed
< // still count towards the total instructions.
< ++valid_num;
< cprintf("Count:%i\n", valid_num);
< }
< }
---
> cprintf("Ready float list size: %i\n", readyFloatInsts.size());
1349,1355c1119
< cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n"
< "Issued:%i\nSquashed:%i\n",
< (*inst_list_it)->readPC(),
< (*inst_list_it)->seqNum,
< (*inst_list_it)->threadNumber,
< (*inst_list_it)->isIssued(),
< (*inst_list_it)->isSquashed());
---
> cprintf("Ready branch list size: %i\n", readyBranchInsts.size());
1357,1359c1121
< if ((*inst_list_it)->isMemRef()) {
< cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone);
< }
---
> cprintf("Ready misc list size: %i\n", readyMiscInsts.size());
1361c1123
< cprintf("\n");
---
> cprintf("Squashed list size: %i\n", squashedInsts.size());
1363,1365c1125,1133
< inst_list_it++;
< ++num;
< }
---
> cprintf("Non speculative list size: %i\n", nonSpecInsts.size());
>
> non_spec_it_t non_spec_it = nonSpecInsts.begin();
>
> cprintf("Non speculative list: ");
>
> while (non_spec_it != nonSpecInsts.end()) {
> cprintf("%#x ", (*non_spec_it).second->readPC());
> ++non_spec_it;
1366a1135,1137
>
> cprintf("\n");
>