inst_queue_impl.hh revision 2665
11689SN/A/* 21689SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan 31689SN/A * All rights reserved. 41689SN/A * 51689SN/A * Redistribution and use in source and binary forms, with or without 61689SN/A * modification, are permitted provided that the following conditions are 71689SN/A * met: redistributions of source code must retain the above copyright 81689SN/A * notice, this list of conditions and the following disclaimer; 91689SN/A * redistributions in binary form must reproduce the above copyright 101689SN/A * notice, this list of conditions and the following disclaimer in the 111689SN/A * documentation and/or other materials provided with the distribution; 121689SN/A * neither the name of the copyright holders nor the names of its 131689SN/A * contributors may be used to endorse or promote products derived from 141689SN/A * this software without specific prior written permission. 151689SN/A * 161689SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181689SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191689SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201689SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211689SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221689SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231689SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241689SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251689SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261689SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * Authors: Kevin Lim 291689SN/A */ 301689SN/A 311061SN/A// Todo: 321061SN/A// Current ordering allows for 0 cycle added-to-scheduled. Could maybe fake 331060SN/A// it; either do in reverse order, or have added instructions put into a 341060SN/A// different ready queue that, in scheduleRreadyInsts(), gets put onto the 351060SN/A// normal ready queue. This would however give only a one cycle delay, 361060SN/A// but probably is more flexible to actually add in a delay parameter than 371060SN/A// just running it backwards. 381060SN/A 392064SN/A#include <limits> 401060SN/A#include <vector> 411060SN/A 421696SN/A#include "sim/root.hh" 431689SN/A 441717SN/A#include "cpu/o3/inst_queue.hh" 451060SN/A 461060SN/A// Either compile error or max int due to sign extension. 471689SN/A// Hack to avoid compile warnings. 482064SN/Aconst InstSeqNum MaxInstSeqNum = std::numeric_limits<InstSeqNum>::max(); 491060SN/A 501061SN/Atemplate <class Impl> 511060SN/AInstructionQueue<Impl>::InstructionQueue(Params ¶ms) 521061SN/A : memDepUnit(params), 531061SN/A numEntries(params.numIQEntries), 541060SN/A intWidth(params.executeIntWidth), 551060SN/A floatWidth(params.executeFloatWidth), 561062SN/A branchWidth(params.executeBranchWidth), 571062SN/A memoryWidth(params.executeMemoryWidth), 581061SN/A totalWidth(params.issueWidth), 591060SN/A numPhysIntRegs(params.numPhysIntRegs), 601060SN/A numPhysFloatRegs(params.numPhysFloatRegs), 611060SN/A commitToIEWDelay(params.commitToIEWDelay) 621060SN/A{ 631060SN/A // Initialize the number of free IQ entries. 641060SN/A freeEntries = numEntries; 651060SN/A 661060SN/A // Set the number of physical registers as the number of int + float 671060SN/A numPhysRegs = numPhysIntRegs + numPhysFloatRegs; 681060SN/A 691060SN/A DPRINTF(IQ, "IQ: There are %i physical registers.\n", numPhysRegs); 701060SN/A 711060SN/A //Create an entry for each physical register within the 721060SN/A //dependency graph. 731060SN/A dependGraph = new DependencyEntry[numPhysRegs]; 741060SN/A 751060SN/A // Resize the register scoreboard. 761060SN/A regScoreboard.resize(numPhysRegs); 771060SN/A 781060SN/A // Initialize all the head pointers to point to NULL, and all the 791060SN/A // entries as unready. 801060SN/A // Note that in actuality, the registers corresponding to the logical 811060SN/A // registers start off as ready. However this doesn't matter for the 821060SN/A // IQ as the instruction should have been correctly told if those 831060SN/A // registers are ready in rename. Thus it can all be initialized as 841060SN/A // unready. 851060SN/A for (int i = 0; i < numPhysRegs; ++i) 861060SN/A { 871060SN/A dependGraph[i].next = NULL; 881060SN/A dependGraph[i].inst = NULL; 891060SN/A regScoreboard[i] = false; 901060SN/A } 911060SN/A 921060SN/A} 931060SN/A 941061SN/Atemplate <class Impl> 951060SN/Avoid 961062SN/AInstructionQueue<Impl>::regStats() 971062SN/A{ 981062SN/A iqInstsAdded 991062SN/A .name(name() + ".iqInstsAdded") 1001062SN/A .desc("Number of instructions added to the IQ (excludes non-spec)") 1011062SN/A .prereq(iqInstsAdded); 1021062SN/A 1031062SN/A iqNonSpecInstsAdded 1041062SN/A .name(name() + ".iqNonSpecInstsAdded") 1051062SN/A .desc("Number of non-speculative instructions added to the IQ") 1061062SN/A .prereq(iqNonSpecInstsAdded); 1071062SN/A 1081062SN/A// iqIntInstsAdded; 1091062SN/A 1101062SN/A iqIntInstsIssued 1111062SN/A .name(name() + ".iqIntInstsIssued") 1121062SN/A .desc("Number of integer instructions issued") 1131062SN/A .prereq(iqIntInstsIssued); 1141062SN/A 1151062SN/A// iqFloatInstsAdded; 1161062SN/A 1171062SN/A iqFloatInstsIssued 1181062SN/A .name(name() + ".iqFloatInstsIssued") 1191062SN/A .desc("Number of float instructions issued") 1201062SN/A .prereq(iqFloatInstsIssued); 1211062SN/A 1221062SN/A// iqBranchInstsAdded; 1231062SN/A 1241062SN/A iqBranchInstsIssued 1251062SN/A .name(name() + ".iqBranchInstsIssued") 1261062SN/A .desc("Number of branch instructions issued") 1271062SN/A .prereq(iqBranchInstsIssued); 1281062SN/A 1291062SN/A// iqMemInstsAdded; 1301062SN/A 1311062SN/A iqMemInstsIssued 1321062SN/A .name(name() + ".iqMemInstsIssued") 1331062SN/A .desc("Number of memory instructions issued") 1341062SN/A .prereq(iqMemInstsIssued); 1351062SN/A 1361062SN/A// iqMiscInstsAdded; 1371062SN/A 1381062SN/A iqMiscInstsIssued 1391062SN/A .name(name() + ".iqMiscInstsIssued") 1401062SN/A .desc("Number of miscellaneous instructions issued") 1411062SN/A .prereq(iqMiscInstsIssued); 1421062SN/A 1431062SN/A iqSquashedInstsIssued 1441062SN/A .name(name() + ".iqSquashedInstsIssued") 1451062SN/A .desc("Number of squashed instructions issued") 1461062SN/A .prereq(iqSquashedInstsIssued); 1471062SN/A 1481062SN/A iqLoopSquashStalls 1491062SN/A .name(name() + ".iqLoopSquashStalls") 1501062SN/A .desc("Number of times issue loop had to restart due to squashed " 1511062SN/A "inst; mainly for profiling") 1521062SN/A .prereq(iqLoopSquashStalls); 1531062SN/A 1541062SN/A iqSquashedInstsExamined 1551062SN/A .name(name() + ".iqSquashedInstsExamined") 1561062SN/A .desc("Number of squashed instructions iterated over during squash;" 1571062SN/A " mainly for profiling") 1581062SN/A .prereq(iqSquashedInstsExamined); 1591062SN/A 1601062SN/A iqSquashedOperandsExamined 1611062SN/A .name(name() + ".iqSquashedOperandsExamined") 1621062SN/A .desc("Number of squashed operands that are examined and possibly " 1631062SN/A "removed from graph") 1641062SN/A .prereq(iqSquashedOperandsExamined); 1651062SN/A 1661062SN/A iqSquashedNonSpecRemoved 1671062SN/A .name(name() + ".iqSquashedNonSpecRemoved") 1681062SN/A .desc("Number of squashed non-spec instructions that were removed") 1691062SN/A .prereq(iqSquashedNonSpecRemoved); 1701062SN/A 1711062SN/A // Tell mem dependence unit to reg stats as well. 1721062SN/A memDepUnit.regStats(); 1731062SN/A} 1741062SN/A 1751062SN/Atemplate <class Impl> 1761062SN/Avoid 1771060SN/AInstructionQueue<Impl>::setCPU(FullCPU *cpu_ptr) 1781060SN/A{ 1791060SN/A cpu = cpu_ptr; 1801060SN/A 1811060SN/A tail = cpu->instList.begin(); 1821060SN/A} 1831060SN/A 1841061SN/Atemplate <class Impl> 1851060SN/Avoid 1861060SN/AInstructionQueue<Impl>::setIssueToExecuteQueue( 1871060SN/A TimeBuffer<IssueStruct> *i2e_ptr) 1881060SN/A{ 1891060SN/A DPRINTF(IQ, "IQ: Set the issue to execute queue.\n"); 1901060SN/A issueToExecuteQueue = i2e_ptr; 1911060SN/A} 1921060SN/A 1931061SN/Atemplate <class Impl> 1941060SN/Avoid 1951060SN/AInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 1961060SN/A{ 1971060SN/A DPRINTF(IQ, "IQ: Set the time buffer.\n"); 1981060SN/A timeBuffer = tb_ptr; 1991060SN/A 2001060SN/A fromCommit = timeBuffer->getWire(-commitToIEWDelay); 2011060SN/A} 2021060SN/A 2031684SN/Atemplate <class Impl> 2041684SN/Aunsigned 2051684SN/AInstructionQueue<Impl>::numFreeEntries() 2061684SN/A{ 2071684SN/A return freeEntries; 2081684SN/A} 2091684SN/A 2101060SN/A// Might want to do something more complex if it knows how many instructions 2111060SN/A// will be issued this cycle. 2121061SN/Atemplate <class Impl> 2131060SN/Abool 2141060SN/AInstructionQueue<Impl>::isFull() 2151060SN/A{ 2161060SN/A if (freeEntries == 0) { 2171060SN/A return(true); 2181060SN/A } else { 2191060SN/A return(false); 2201060SN/A } 2211060SN/A} 2221060SN/A 2231061SN/Atemplate <class Impl> 2241060SN/Avoid 2251061SN/AInstructionQueue<Impl>::insert(DynInstPtr &new_inst) 2261060SN/A{ 2271060SN/A // Make sure the instruction is valid 2281060SN/A assert(new_inst); 2291060SN/A 2301060SN/A DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 2311060SN/A new_inst->readPC()); 2321060SN/A 2331060SN/A // Check if there are any free entries. Panic if there are none. 2341060SN/A // Might want to have this return a fault in the future instead of 2351060SN/A // panicing. 2361060SN/A assert(freeEntries != 0); 2371060SN/A 2381060SN/A // If the IQ currently has nothing in it, then there's a possibility 2391060SN/A // that the tail iterator is invalid (might have been pointing at an 2401060SN/A // instruction that was retired). Reset the tail iterator. 2411060SN/A if (freeEntries == numEntries) { 2421060SN/A tail = cpu->instList.begin(); 2431060SN/A } 2441060SN/A 2451060SN/A // Move the tail iterator. Instructions may not have been issued 2461060SN/A // to the IQ, so we may have to increment the iterator more than once. 2471060SN/A while ((*tail) != new_inst) { 2481060SN/A tail++; 2491060SN/A 2501060SN/A // Make sure the tail iterator points at something legal. 2511060SN/A assert(tail != cpu->instList.end()); 2521060SN/A } 2531060SN/A 2541060SN/A 2551060SN/A // Decrease the number of free entries. 2561060SN/A --freeEntries; 2571060SN/A 2581060SN/A // Look through its source registers (physical regs), and mark any 2591060SN/A // dependencies. 2601060SN/A addToDependents(new_inst); 2611060SN/A 2621060SN/A // Have this instruction set itself as the producer of its destination 2631060SN/A // register(s). 2641060SN/A createDependency(new_inst); 2651060SN/A 2661061SN/A // If it's a memory instruction, add it to the memory dependency 2671061SN/A // unit. 2681061SN/A if (new_inst->isMemRef()) { 2691061SN/A memDepUnit.insert(new_inst); 2701062SN/A // Uh..forgot to look it up and put it on the proper dependency list 2711062SN/A // if the instruction should not go yet. 2721062SN/A } else { 2731062SN/A // If the instruction is ready then add it to the ready list. 2741062SN/A addIfReady(new_inst); 2751061SN/A } 2761061SN/A 2771062SN/A ++iqInstsAdded; 2781060SN/A 2791060SN/A assert(freeEntries == (numEntries - countInsts())); 2801060SN/A} 2811060SN/A 2821061SN/Atemplate <class Impl> 2831061SN/Avoid 2841061SN/AInstructionQueue<Impl>::insertNonSpec(DynInstPtr &inst) 2851061SN/A{ 2861061SN/A nonSpecInsts[inst->seqNum] = inst; 2871061SN/A 2881061SN/A // @todo: Clean up this code; can do it by setting inst as unable 2891061SN/A // to issue, then calling normal insert on the inst. 2901061SN/A 2911061SN/A // Make sure the instruction is valid 2921061SN/A assert(inst); 2931061SN/A 2941061SN/A DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 2951061SN/A inst->readPC()); 2961061SN/A 2971061SN/A // Check if there are any free entries. Panic if there are none. 2981061SN/A // Might want to have this return a fault in the future instead of 2991061SN/A // panicing. 3001061SN/A assert(freeEntries != 0); 3011061SN/A 3021061SN/A // If the IQ currently has nothing in it, then there's a possibility 3031061SN/A // that the tail iterator is invalid (might have been pointing at an 3041061SN/A // instruction that was retired). Reset the tail iterator. 3051061SN/A if (freeEntries == numEntries) { 3061061SN/A tail = cpu->instList.begin(); 3071061SN/A } 3081061SN/A 3091061SN/A // Move the tail iterator. Instructions may not have been issued 3101061SN/A // to the IQ, so we may have to increment the iterator more than once. 3111061SN/A while ((*tail) != inst) { 3121061SN/A tail++; 3131061SN/A 3141061SN/A // Make sure the tail iterator points at something legal. 3151061SN/A assert(tail != cpu->instList.end()); 3161061SN/A } 3171061SN/A 3181061SN/A // Decrease the number of free entries. 3191061SN/A --freeEntries; 3201061SN/A 3211061SN/A // Have this instruction set itself as the producer of its destination 3221061SN/A // register(s). 3231061SN/A createDependency(inst); 3241061SN/A 3251061SN/A // If it's a memory instruction, add it to the memory dependency 3261061SN/A // unit. 3271061SN/A if (inst->isMemRef()) { 3281062SN/A memDepUnit.insertNonSpec(inst); 3291061SN/A } 3301062SN/A 3311062SN/A ++iqNonSpecInstsAdded; 3321061SN/A} 3331061SN/A 3341060SN/A// Slightly hack function to advance the tail iterator in the case that 3351060SN/A// the IEW stage issues an instruction that is not added to the IQ. This 3361060SN/A// is needed in case a long chain of such instructions occurs. 3371062SN/A// I don't think this is used anymore. 3381061SN/Atemplate <class Impl> 3391060SN/Avoid 3401061SN/AInstructionQueue<Impl>::advanceTail(DynInstPtr &inst) 3411060SN/A{ 3421060SN/A // Make sure the instruction is valid 3431060SN/A assert(inst); 3441060SN/A 3451060SN/A DPRINTF(IQ, "IQ: Adding instruction PC %#x to the IQ.\n", 3461060SN/A inst->readPC()); 3471060SN/A 3481060SN/A // Check if there are any free entries. Panic if there are none. 3491060SN/A // Might want to have this return a fault in the future instead of 3501060SN/A // panicing. 3511060SN/A assert(freeEntries != 0); 3521060SN/A 3531060SN/A // If the IQ currently has nothing in it, then there's a possibility 3541060SN/A // that the tail iterator is invalid (might have been pointing at an 3551060SN/A // instruction that was retired). Reset the tail iterator. 3561060SN/A if (freeEntries == numEntries) { 3571060SN/A tail = cpu->instList.begin(); 3581060SN/A } 3591060SN/A 3601060SN/A // Move the tail iterator. Instructions may not have been issued 3611060SN/A // to the IQ, so we may have to increment the iterator more than once. 3621060SN/A while ((*tail) != inst) { 3631060SN/A tail++; 3641060SN/A 3651060SN/A // Make sure the tail iterator points at something legal. 3661060SN/A assert(tail != cpu->instList.end()); 3671060SN/A } 3681060SN/A 3691060SN/A assert(freeEntries <= numEntries); 3701060SN/A 3711060SN/A // Have this instruction set itself as the producer of its destination 3721060SN/A // register(s). 3731060SN/A createDependency(inst); 3741060SN/A} 3751060SN/A 3761060SN/A// Need to make sure the number of float and integer instructions 3771061SN/A// issued does not exceed the total issue bandwidth. 3781061SN/A// @todo: Figure out a better way to remove the squashed items from the 3791061SN/A// lists. Checking the top item of each list to see if it's squashed 3801061SN/A// wastes time and forces jumps. 3811061SN/Atemplate <class Impl> 3821060SN/Avoid 3831060SN/AInstructionQueue<Impl>::scheduleReadyInsts() 3841060SN/A{ 3851060SN/A DPRINTF(IQ, "IQ: Attempting to schedule ready instructions from " 3861060SN/A "the IQ.\n"); 3871060SN/A 3881060SN/A int int_issued = 0; 3891060SN/A int float_issued = 0; 3901060SN/A int branch_issued = 0; 3911061SN/A int memory_issued = 0; 3921060SN/A int squashed_issued = 0; 3931060SN/A int total_issued = 0; 3941060SN/A 3951060SN/A IssueStruct *i2e_info = issueToExecuteQueue->access(0); 3961060SN/A 3971060SN/A bool insts_available = !readyBranchInsts.empty() || 3981060SN/A !readyIntInsts.empty() || 3991060SN/A !readyFloatInsts.empty() || 4001062SN/A !memDepUnit.empty() || 4011061SN/A !readyMiscInsts.empty() || 4021060SN/A !squashedInsts.empty(); 4031060SN/A 4041060SN/A // Note: Requires a globally defined constant. 4051060SN/A InstSeqNum oldest_inst = MaxInstSeqNum; 4061060SN/A InstList list_with_oldest = None; 4071060SN/A 4081060SN/A // Temporary values. 4091061SN/A DynInstPtr int_head_inst; 4101061SN/A DynInstPtr float_head_inst; 4111061SN/A DynInstPtr branch_head_inst; 4121061SN/A DynInstPtr mem_head_inst; 4131061SN/A DynInstPtr misc_head_inst; 4141061SN/A DynInstPtr squashed_head_inst; 4151060SN/A 4161060SN/A // Somewhat nasty code to look at all of the lists where issuable 4171060SN/A // instructions are located, and choose the oldest instruction among 4181060SN/A // those lists. Consider a rewrite in the future. 4191060SN/A while (insts_available && total_issued < totalWidth) 4201060SN/A { 4211060SN/A // Set this to false. Each if-block is required to set it to true 4221060SN/A // if there were instructions available this check. This will cause 4231060SN/A // this loop to run once more than necessary, but avoids extra calls. 4241060SN/A insts_available = false; 4251060SN/A 4261060SN/A oldest_inst = MaxInstSeqNum; 4271060SN/A 4281060SN/A list_with_oldest = None; 4291060SN/A 4301060SN/A if (!readyIntInsts.empty() && 4311060SN/A int_issued < intWidth) { 4321060SN/A 4331060SN/A insts_available = true; 4341060SN/A 4351061SN/A int_head_inst = readyIntInsts.top(); 4361060SN/A 4371060SN/A if (int_head_inst->isSquashed()) { 4381060SN/A readyIntInsts.pop(); 4391062SN/A 4401062SN/A ++iqLoopSquashStalls; 4411062SN/A 4421060SN/A continue; 4431060SN/A } 4441060SN/A 4451060SN/A oldest_inst = int_head_inst->seqNum; 4461060SN/A 4471060SN/A list_with_oldest = Int; 4481060SN/A } 4491060SN/A 4501060SN/A if (!readyFloatInsts.empty() && 4511060SN/A float_issued < floatWidth) { 4521060SN/A 4531060SN/A insts_available = true; 4541060SN/A 4551061SN/A float_head_inst = readyFloatInsts.top(); 4561060SN/A 4571060SN/A if (float_head_inst->isSquashed()) { 4581060SN/A readyFloatInsts.pop(); 4591062SN/A 4601062SN/A ++iqLoopSquashStalls; 4611062SN/A 4621060SN/A continue; 4631060SN/A } else if (float_head_inst->seqNum < oldest_inst) { 4641060SN/A oldest_inst = float_head_inst->seqNum; 4651060SN/A 4661060SN/A list_with_oldest = Float; 4671060SN/A } 4681060SN/A } 4691060SN/A 4701060SN/A if (!readyBranchInsts.empty() && 4711060SN/A branch_issued < branchWidth) { 4721060SN/A 4731060SN/A insts_available = true; 4741060SN/A 4751061SN/A branch_head_inst = readyBranchInsts.top(); 4761060SN/A 4771060SN/A if (branch_head_inst->isSquashed()) { 4781060SN/A readyBranchInsts.pop(); 4791062SN/A 4801062SN/A ++iqLoopSquashStalls; 4811062SN/A 4821060SN/A continue; 4831060SN/A } else if (branch_head_inst->seqNum < oldest_inst) { 4841060SN/A oldest_inst = branch_head_inst->seqNum; 4851060SN/A 4861060SN/A list_with_oldest = Branch; 4871060SN/A } 4881060SN/A 4891060SN/A } 4901060SN/A 4911062SN/A if (!memDepUnit.empty() && 4921061SN/A memory_issued < memoryWidth) { 4931061SN/A 4941061SN/A insts_available = true; 4951061SN/A 4961062SN/A mem_head_inst = memDepUnit.top(); 4971061SN/A 4981061SN/A if (mem_head_inst->isSquashed()) { 4991062SN/A memDepUnit.pop(); 5001062SN/A 5011062SN/A ++iqLoopSquashStalls; 5021062SN/A 5031061SN/A continue; 5041061SN/A } else if (mem_head_inst->seqNum < oldest_inst) { 5051061SN/A oldest_inst = mem_head_inst->seqNum; 5061061SN/A 5071061SN/A list_with_oldest = Memory; 5081061SN/A } 5091061SN/A } 5101061SN/A 5111061SN/A if (!readyMiscInsts.empty()) { 5121061SN/A 5131061SN/A insts_available = true; 5141061SN/A 5151061SN/A misc_head_inst = readyMiscInsts.top(); 5161061SN/A 5171061SN/A if (misc_head_inst->isSquashed()) { 5181061SN/A readyMiscInsts.pop(); 5191062SN/A 5201062SN/A ++iqLoopSquashStalls; 5211062SN/A 5221061SN/A continue; 5231061SN/A } else if (misc_head_inst->seqNum < oldest_inst) { 5241061SN/A oldest_inst = misc_head_inst->seqNum; 5251061SN/A 5261061SN/A list_with_oldest = Misc; 5271061SN/A } 5281061SN/A } 5291061SN/A 5301060SN/A if (!squashedInsts.empty()) { 5311060SN/A 5321060SN/A insts_available = true; 5331060SN/A 5341061SN/A squashed_head_inst = squashedInsts.top(); 5351060SN/A 5361060SN/A if (squashed_head_inst->seqNum < oldest_inst) { 5371060SN/A list_with_oldest = Squashed; 5381060SN/A } 5391060SN/A 5401060SN/A } 5411060SN/A 5421061SN/A DynInstPtr issuing_inst = NULL; 5431060SN/A 5441060SN/A switch (list_with_oldest) { 5451060SN/A case None: 5461060SN/A DPRINTF(IQ, "IQ: Not able to schedule any instructions. Issuing " 5471060SN/A "inst is %#x.\n", issuing_inst); 5481060SN/A break; 5491061SN/A 5501060SN/A case Int: 5511060SN/A issuing_inst = int_head_inst; 5521060SN/A readyIntInsts.pop(); 5531060SN/A ++int_issued; 5541060SN/A DPRINTF(IQ, "IQ: Issuing integer instruction PC %#x.\n", 5551060SN/A issuing_inst->readPC()); 5561060SN/A break; 5571061SN/A 5581060SN/A case Float: 5591060SN/A issuing_inst = float_head_inst; 5601060SN/A readyFloatInsts.pop(); 5611060SN/A ++float_issued; 5621060SN/A DPRINTF(IQ, "IQ: Issuing float instruction PC %#x.\n", 5631060SN/A issuing_inst->readPC()); 5641060SN/A break; 5651061SN/A 5661060SN/A case Branch: 5671060SN/A issuing_inst = branch_head_inst; 5681060SN/A readyBranchInsts.pop(); 5691060SN/A ++branch_issued; 5701060SN/A DPRINTF(IQ, "IQ: Issuing branch instruction PC %#x.\n", 5711060SN/A issuing_inst->readPC()); 5721060SN/A break; 5731061SN/A 5741061SN/A case Memory: 5751061SN/A issuing_inst = mem_head_inst; 5761061SN/A 5771062SN/A memDepUnit.pop(); 5781061SN/A ++memory_issued; 5791061SN/A DPRINTF(IQ, "IQ: Issuing memory instruction PC %#x.\n", 5801061SN/A issuing_inst->readPC()); 5811061SN/A break; 5821061SN/A 5831061SN/A case Misc: 5841061SN/A issuing_inst = misc_head_inst; 5851061SN/A readyMiscInsts.pop(); 5861062SN/A 5871062SN/A ++iqMiscInstsIssued; 5881062SN/A 5891061SN/A DPRINTF(IQ, "IQ: Issuing a miscellaneous instruction PC %#x.\n", 5901061SN/A issuing_inst->readPC()); 5911061SN/A break; 5921061SN/A 5931060SN/A case Squashed: 5941681SN/A assert(0 && "Squashed insts should not issue any more!"); 5951060SN/A squashedInsts.pop(); 5961681SN/A // Set the squashed instruction as able to commit so that commit 5971681SN/A // can just drop it from the ROB. This is a bit faked. 5981060SN/A ++squashed_issued; 5991681SN/A ++freeEntries; 6001681SN/A 6011060SN/A DPRINTF(IQ, "IQ: Issuing squashed instruction PC %#x.\n", 6021681SN/A squashed_head_inst->readPC()); 6031060SN/A break; 6041060SN/A } 6051060SN/A 6061681SN/A if (list_with_oldest != None && list_with_oldest != Squashed) { 6071060SN/A i2e_info->insts[total_issued] = issuing_inst; 6081062SN/A i2e_info->size++; 6091060SN/A 6101060SN/A issuing_inst->setIssued(); 6111060SN/A 6121060SN/A ++freeEntries; 6131060SN/A ++total_issued; 6141060SN/A } 6151060SN/A 6161060SN/A assert(freeEntries == (numEntries - countInsts())); 6171060SN/A } 6181062SN/A 6191062SN/A iqIntInstsIssued += int_issued; 6201062SN/A iqFloatInstsIssued += float_issued; 6211062SN/A iqBranchInstsIssued += branch_issued; 6221062SN/A iqMemInstsIssued += memory_issued; 6231062SN/A iqSquashedInstsIssued += squashed_issued; 6241060SN/A} 6251060SN/A 6261061SN/Atemplate <class Impl> 6271060SN/Avoid 6281061SN/AInstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst) 6291060SN/A{ 6301062SN/A DPRINTF(IQ, "IQ: Marking nonspeculative instruction with sequence " 6311062SN/A "number %i as ready to execute.\n", inst); 6321062SN/A 6331061SN/A non_spec_it_t inst_it = nonSpecInsts.find(inst); 6341060SN/A 6351061SN/A assert(inst_it != nonSpecInsts.end()); 6361060SN/A 6371061SN/A // Mark this instruction as ready to issue. 6381061SN/A (*inst_it).second->setCanIssue(); 6391060SN/A 6401061SN/A // Now schedule the instruction. 6411062SN/A if (!(*inst_it).second->isMemRef()) { 6421062SN/A addIfReady((*inst_it).second); 6431062SN/A } else { 6441062SN/A memDepUnit.nonSpecInstReady((*inst_it).second); 6451062SN/A } 6461060SN/A 6471061SN/A nonSpecInsts.erase(inst_it); 6481060SN/A} 6491060SN/A 6501061SN/Atemplate <class Impl> 6511061SN/Avoid 6521684SN/AInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst) 6531684SN/A{ 6541684SN/A DPRINTF(IQ, "IQ: Waking dependents of completed instruction.\n"); 6551684SN/A //Look at the physical destination register of the DynInst 6561684SN/A //and look it up on the dependency graph. Then mark as ready 6571684SN/A //any instructions within the instruction queue. 6581684SN/A DependencyEntry *curr; 6591684SN/A 6601684SN/A // Tell the memory dependence unit to wake any dependents on this 6611684SN/A // instruction if it is a memory instruction. 6621684SN/A 6631684SN/A if (completed_inst->isMemRef()) { 6641684SN/A memDepUnit.wakeDependents(completed_inst); 6651684SN/A } 6661684SN/A 6671684SN/A for (int dest_reg_idx = 0; 6681684SN/A dest_reg_idx < completed_inst->numDestRegs(); 6691684SN/A dest_reg_idx++) 6701684SN/A { 6711684SN/A PhysRegIndex dest_reg = 6721684SN/A completed_inst->renamedDestRegIdx(dest_reg_idx); 6731684SN/A 6741684SN/A // Special case of uniq or control registers. They are not 6751684SN/A // handled by the IQ and thus have no dependency graph entry. 6761684SN/A // @todo Figure out a cleaner way to handle this. 6771684SN/A if (dest_reg >= numPhysRegs) { 6781684SN/A continue; 6791684SN/A } 6801684SN/A 6811684SN/A DPRINTF(IQ, "IQ: Waking any dependents on register %i.\n", 6821684SN/A (int) dest_reg); 6831684SN/A 6841684SN/A //Maybe abstract this part into a function. 6851684SN/A //Go through the dependency chain, marking the registers as ready 6861684SN/A //within the waiting instructions. 6871684SN/A while (dependGraph[dest_reg].next) { 6881684SN/A 6891684SN/A curr = dependGraph[dest_reg].next; 6901684SN/A 6911684SN/A DPRINTF(IQ, "IQ: Waking up a dependent instruction, PC%#x.\n", 6921684SN/A curr->inst->readPC()); 6931684SN/A 6941684SN/A // Might want to give more information to the instruction 6951684SN/A // so that it knows which of its source registers is ready. 6961684SN/A // However that would mean that the dependency graph entries 6971684SN/A // would need to hold the src_reg_idx. 6981684SN/A curr->inst->markSrcRegReady(); 6991684SN/A 7001684SN/A addIfReady(curr->inst); 7011684SN/A 7021684SN/A dependGraph[dest_reg].next = curr->next; 7031684SN/A 7041684SN/A DependencyEntry::mem_alloc_counter--; 7051684SN/A 7061684SN/A curr->inst = NULL; 7071684SN/A 7081684SN/A delete curr; 7091684SN/A } 7101684SN/A 7111684SN/A // Reset the head node now that all of its dependents have been woken 7121684SN/A // up. 7131684SN/A dependGraph[dest_reg].next = NULL; 7141684SN/A dependGraph[dest_reg].inst = NULL; 7151684SN/A 7161684SN/A // Mark the scoreboard as having that register ready. 7171684SN/A regScoreboard[dest_reg] = true; 7181684SN/A } 7191684SN/A} 7201684SN/A 7211684SN/Atemplate <class Impl> 7221684SN/Avoid 7231061SN/AInstructionQueue<Impl>::violation(DynInstPtr &store, 7241061SN/A DynInstPtr &faulting_load) 7251061SN/A{ 7261061SN/A memDepUnit.violation(store, faulting_load); 7271061SN/A} 7281061SN/A 7291061SN/Atemplate <class Impl> 7301060SN/Avoid 7311060SN/AInstructionQueue<Impl>::squash() 7321060SN/A{ 7331060SN/A DPRINTF(IQ, "IQ: Starting to squash instructions in the IQ.\n"); 7341060SN/A 7351060SN/A // Read instruction sequence number of last instruction out of the 7361060SN/A // time buffer. 7371060SN/A squashedSeqNum = fromCommit->commitInfo.doneSeqNum; 7381060SN/A 7391060SN/A // Setup the squash iterator to point to the tail. 7401060SN/A squashIt = tail; 7411060SN/A 7421681SN/A // Call doSquash if there are insts in the IQ 7431681SN/A if (freeEntries != numEntries) { 7441681SN/A doSquash(); 7451681SN/A } 7461061SN/A 7471061SN/A // Also tell the memory dependence unit to squash. 7481061SN/A memDepUnit.squash(squashedSeqNum); 7491060SN/A} 7501060SN/A 7511061SN/Atemplate <class Impl> 7521061SN/Avoid 7531061SN/AInstructionQueue<Impl>::doSquash() 7541061SN/A{ 7551061SN/A // Make sure the squash iterator isn't pointing to nothing. 7561061SN/A assert(squashIt != cpu->instList.end()); 7571061SN/A // Make sure the squashed sequence number is valid. 7581061SN/A assert(squashedSeqNum != 0); 7591061SN/A 7601061SN/A DPRINTF(IQ, "IQ: Squashing instructions in the IQ.\n"); 7611061SN/A 7621061SN/A // Squash any instructions younger than the squashed sequence number 7631061SN/A // given. 7641061SN/A while ((*squashIt)->seqNum > squashedSeqNum) { 7651061SN/A DynInstPtr squashed_inst = (*squashIt); 7661061SN/A 7671061SN/A // Only handle the instruction if it actually is in the IQ and 7681061SN/A // hasn't already been squashed in the IQ. 7691061SN/A if (!squashed_inst->isIssued() && 7701061SN/A !squashed_inst->isSquashedInIQ()) { 7711062SN/A 7721061SN/A // Remove the instruction from the dependency list. 7731061SN/A // Hack for now: These below don't add themselves to the 7741061SN/A // dependency list, so don't try to remove them. 7751681SN/A if (!squashed_inst->isNonSpeculative()/* && 7761681SN/A !squashed_inst->isStore()*/ 7771681SN/A ) { 7781061SN/A 7791061SN/A for (int src_reg_idx = 0; 7801681SN/A src_reg_idx < squashed_inst->numSrcRegs(); 7811061SN/A src_reg_idx++) 7821061SN/A { 7831061SN/A PhysRegIndex src_reg = 7841061SN/A squashed_inst->renamedSrcRegIdx(src_reg_idx); 7851061SN/A 7861061SN/A // Only remove it from the dependency graph if it was 7871061SN/A // placed there in the first place. 7881061SN/A // HACK: This assumes that instructions woken up from the 7891061SN/A // dependency chain aren't informed that a specific src 7901061SN/A // register has become ready. This may not always be true 7911061SN/A // in the future. 7921061SN/A if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) && 7931061SN/A src_reg < numPhysRegs) { 7941061SN/A dependGraph[src_reg].remove(squashed_inst); 7951061SN/A } 7961062SN/A 7971062SN/A ++iqSquashedOperandsExamined; 7981061SN/A } 7991062SN/A 8001062SN/A // Might want to remove producers as well. 8011062SN/A } else { 8021681SN/A nonSpecInsts[squashed_inst->seqNum] = NULL; 8031681SN/A 8041062SN/A nonSpecInsts.erase(squashed_inst->seqNum); 8051062SN/A 8061062SN/A ++iqSquashedNonSpecRemoved; 8071061SN/A } 8081061SN/A 8091061SN/A // Might want to also clear out the head of the dependency graph. 8101061SN/A 8111061SN/A // Mark it as squashed within the IQ. 8121061SN/A squashed_inst->setSquashedInIQ(); 8131061SN/A 8141681SN/A// squashedInsts.push(squashed_inst); 8151681SN/A squashed_inst->setIssued(); 8161681SN/A squashed_inst->setCanCommit(); 8171681SN/A 8181681SN/A ++freeEntries; 8191061SN/A 8201061SN/A DPRINTF(IQ, "IQ: Instruction PC %#x squashed.\n", 8211061SN/A squashed_inst->readPC()); 8221061SN/A } 8231061SN/A 8241061SN/A --squashIt; 8251062SN/A ++iqSquashedInstsExamined; 8261061SN/A } 8271681SN/A 8281681SN/A assert(freeEntries <= numEntries); 8291681SN/A 8301681SN/A if (freeEntries == numEntries) { 8311681SN/A tail = cpu->instList.end(); 8321681SN/A } 8331681SN/A 8341061SN/A} 8351061SN/A 8361061SN/Atemplate <class Impl> 8371060SN/Avoid 8381060SN/AInstructionQueue<Impl>::stopSquash() 8391060SN/A{ 8401060SN/A // Clear up the squash variables to ensure that squashing doesn't 8411060SN/A // get called improperly. 8421060SN/A squashedSeqNum = 0; 8431060SN/A 8441060SN/A squashIt = cpu->instList.end(); 8451060SN/A} 8461060SN/A 8471061SN/Atemplate <class Impl> 8481060SN/Avoid 8491684SN/AInstructionQueue<Impl>::DependencyEntry::insert(DynInstPtr &new_inst) 8501060SN/A{ 8511684SN/A //Add this new, dependent instruction at the head of the dependency 8521684SN/A //chain. 8531060SN/A 8541684SN/A // First create the entry that will be added to the head of the 8551684SN/A // dependency chain. 8561684SN/A DependencyEntry *new_entry = new DependencyEntry; 8571684SN/A new_entry->next = this->next; 8581684SN/A new_entry->inst = new_inst; 8591061SN/A 8601684SN/A // Then actually add it to the chain. 8611684SN/A this->next = new_entry; 8621684SN/A 8631684SN/A ++mem_alloc_counter; 8641684SN/A} 8651684SN/A 8661684SN/Atemplate <class Impl> 8671684SN/Avoid 8681684SN/AInstructionQueue<Impl>::DependencyEntry::remove(DynInstPtr &inst_to_remove) 8691684SN/A{ 8701684SN/A DependencyEntry *prev = this; 8711684SN/A DependencyEntry *curr = this->next; 8721684SN/A 8731684SN/A // Make sure curr isn't NULL. Because this instruction is being 8741684SN/A // removed from a dependency list, it must have been placed there at 8751684SN/A // an earlier time. The dependency chain should not be empty, 8761684SN/A // unless the instruction dependent upon it is already ready. 8771684SN/A if (curr == NULL) { 8781684SN/A return; 8791061SN/A } 8801061SN/A 8811684SN/A // Find the instruction to remove within the dependency linked list. 8821684SN/A while(curr->inst != inst_to_remove) 8831060SN/A { 8841684SN/A prev = curr; 8851684SN/A curr = curr->next; 8861060SN/A 8871684SN/A assert(curr != NULL); 8881684SN/A } 8891060SN/A 8901684SN/A // Now remove this instruction from the list. 8911684SN/A prev->next = curr->next; 8921060SN/A 8931684SN/A --mem_alloc_counter; 8941060SN/A 8951684SN/A // Could push this off to the destructor of DependencyEntry 8961684SN/A curr->inst = NULL; 8971060SN/A 8981684SN/A delete curr; 8991060SN/A} 9001060SN/A 9011061SN/Atemplate <class Impl> 9021060SN/Abool 9031061SN/AInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) 9041060SN/A{ 9051060SN/A // Loop through the instruction's source registers, adding 9061060SN/A // them to the dependency list if they are not ready. 9071060SN/A int8_t total_src_regs = new_inst->numSrcRegs(); 9081060SN/A bool return_val = false; 9091060SN/A 9101060SN/A for (int src_reg_idx = 0; 9111060SN/A src_reg_idx < total_src_regs; 9121060SN/A src_reg_idx++) 9131060SN/A { 9141060SN/A // Only add it to the dependency graph if it's not ready. 9151060SN/A if (!new_inst->isReadySrcRegIdx(src_reg_idx)) { 9161060SN/A PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); 9171060SN/A 9181060SN/A // Check the IQ's scoreboard to make sure the register 9191060SN/A // hasn't become ready while the instruction was in flight 9201060SN/A // between stages. Only if it really isn't ready should 9211060SN/A // it be added to the dependency graph. 9221061SN/A if (src_reg >= numPhysRegs) { 9231061SN/A continue; 9241061SN/A } else if (regScoreboard[src_reg] == false) { 9251060SN/A DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " 9261060SN/A "is being added to the dependency chain.\n", 9271060SN/A new_inst->readPC(), src_reg); 9281060SN/A 9291060SN/A dependGraph[src_reg].insert(new_inst); 9301060SN/A 9311060SN/A // Change the return value to indicate that something 9321060SN/A // was added to the dependency graph. 9331060SN/A return_val = true; 9341060SN/A } else { 9351060SN/A DPRINTF(IQ, "IQ: Instruction PC %#x has src reg %i that " 9361060SN/A "became ready before it reached the IQ.\n", 9371060SN/A new_inst->readPC(), src_reg); 9381060SN/A // Mark a register ready within the instruction. 9391060SN/A new_inst->markSrcRegReady(); 9401060SN/A } 9411060SN/A } 9421060SN/A } 9431060SN/A 9441060SN/A return return_val; 9451060SN/A} 9461060SN/A 9471061SN/Atemplate <class Impl> 9481060SN/Avoid 9491061SN/AInstructionQueue<Impl>::createDependency(DynInstPtr &new_inst) 9501060SN/A{ 9511060SN/A //Actually nothing really needs to be marked when an 9521060SN/A //instruction becomes the producer of a register's value, 9531060SN/A //but for convenience a ptr to the producing instruction will 9541060SN/A //be placed in the head node of the dependency links. 9551060SN/A int8_t total_dest_regs = new_inst->numDestRegs(); 9561060SN/A 9571060SN/A for (int dest_reg_idx = 0; 9581060SN/A dest_reg_idx < total_dest_regs; 9591060SN/A dest_reg_idx++) 9601060SN/A { 9611061SN/A PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); 9621061SN/A 9631061SN/A // Instructions that use the misc regs will have a reg number 9641061SN/A // higher than the normal physical registers. In this case these 9651061SN/A // registers are not renamed, and there is no need to track 9661061SN/A // dependencies as these instructions must be executed at commit. 9671061SN/A if (dest_reg >= numPhysRegs) { 9681061SN/A continue; 9691060SN/A } 9701060SN/A 9711061SN/A dependGraph[dest_reg].inst = new_inst; 9721062SN/A 9731681SN/A if (dependGraph[dest_reg].next) { 9741681SN/A dumpDependGraph(); 9751681SN/A panic("IQ: Dependency graph not empty!"); 9761681SN/A } 9771062SN/A 9781060SN/A // Mark the scoreboard to say it's not yet ready. 9791060SN/A regScoreboard[dest_reg] = false; 9801060SN/A } 9811060SN/A} 9821060SN/A 9831061SN/Atemplate <class Impl> 9841060SN/Avoid 9851061SN/AInstructionQueue<Impl>::addIfReady(DynInstPtr &inst) 9861060SN/A{ 9871060SN/A //If the instruction now has all of its source registers 9881060SN/A // available, then add it to the list of ready instructions. 9891060SN/A if (inst->readyToIssue()) { 9901061SN/A 9911060SN/A //Add the instruction to the proper ready list. 9921061SN/A if (inst->isControl()) { 9931061SN/A 9941061SN/A DPRINTF(IQ, "IQ: Branch instruction is ready to issue, " 9951061SN/A "putting it onto the ready list, PC %#x.\n", 9961061SN/A inst->readPC()); 9971061SN/A readyBranchInsts.push(inst); 9981061SN/A 9991061SN/A } else if (inst->isMemRef()) { 10001061SN/A 10011061SN/A DPRINTF(IQ, "IQ: Checking if memory instruction can issue.\n"); 10021061SN/A 10031062SN/A // Message to the mem dependence unit that this instruction has 10041062SN/A // its registers ready. 10051062SN/A 10061062SN/A memDepUnit.regsReady(inst); 10071062SN/A 10081062SN/A#if 0 10091061SN/A if (memDepUnit.readyToIssue(inst)) { 10101061SN/A DPRINTF(IQ, "IQ: Memory instruction is ready to issue, " 10111061SN/A "putting it onto the ready list, PC %#x.\n", 10121061SN/A inst->readPC()); 10131061SN/A readyMemInsts.push(inst); 10141062SN/A } else { 10151062SN/A // Make dependent on the store. 10161062SN/A // Will need some way to get the store instruction it should 10171062SN/A // be dependent upon; then when the store issues it can 10181062SN/A // put the instruction on the ready list. 10191062SN/A // Yet another tree? 10201062SN/A assert(0 && "Instruction has no way to actually issue"); 10211061SN/A } 10221062SN/A#endif 10231061SN/A 10241061SN/A } else if (inst->isInteger()) { 10251061SN/A 10261060SN/A DPRINTF(IQ, "IQ: Integer instruction is ready to issue, " 10271060SN/A "putting it onto the ready list, PC %#x.\n", 10281060SN/A inst->readPC()); 10291061SN/A readyIntInsts.push(inst); 10301061SN/A 10311060SN/A } else if (inst->isFloating()) { 10321061SN/A 10331060SN/A DPRINTF(IQ, "IQ: Floating instruction is ready to issue, " 10341060SN/A "putting it onto the ready list, PC %#x.\n", 10351060SN/A inst->readPC()); 10361061SN/A readyFloatInsts.push(inst); 10371061SN/A 10381061SN/A } else { 10391061SN/A DPRINTF(IQ, "IQ: Miscellaneous instruction is ready to issue, " 10401061SN/A "putting it onto the ready list, PC %#x..\n", 10411060SN/A inst->readPC()); 10421061SN/A 10431061SN/A readyMiscInsts.push(inst); 10441060SN/A } 10451060SN/A } 10461060SN/A} 10471060SN/A 10481681SN/A/* 10491681SN/A * Caution, this function must not be called prior to tail being updated at 10501681SN/A * least once, otherwise it will fail the assertion. This is because 10511681SN/A * instList.begin() actually changes upon the insertion of an element into the 10521681SN/A * list when the list is empty. 10531681SN/A */ 10541061SN/Atemplate <class Impl> 10551061SN/Aint 10561061SN/AInstructionQueue<Impl>::countInsts() 10571061SN/A{ 10581061SN/A ListIt count_it = cpu->instList.begin(); 10591061SN/A int total_insts = 0; 10601061SN/A 10611681SN/A if (tail == cpu->instList.end()) 10621681SN/A return 0; 10631681SN/A 10641061SN/A while (count_it != tail) { 10651061SN/A if (!(*count_it)->isIssued()) { 10661061SN/A ++total_insts; 10671061SN/A } 10681061SN/A 10691061SN/A ++count_it; 10701061SN/A 10711061SN/A assert(count_it != cpu->instList.end()); 10721061SN/A } 10731061SN/A 10741061SN/A // Need to count the tail iterator as well. 10751061SN/A if (count_it != cpu->instList.end() && 10761061SN/A (*count_it) && 10771061SN/A !(*count_it)->isIssued()) { 10781061SN/A ++total_insts; 10791061SN/A } 10801061SN/A 10811061SN/A return total_insts; 10821061SN/A} 10831061SN/A 10841061SN/Atemplate <class Impl> 10851061SN/Avoid 10861681SN/AInstructionQueue<Impl>::dumpDependGraph() 10871681SN/A{ 10881681SN/A DependencyEntry *curr; 10891681SN/A 10901681SN/A for (int i = 0; i < numPhysRegs; ++i) 10911681SN/A { 10921681SN/A curr = &dependGraph[i]; 10931681SN/A 10941681SN/A if (curr->inst) { 10951681SN/A cprintf("dependGraph[%i]: producer: %#x consumer: ", i, 10961681SN/A curr->inst->readPC()); 10971681SN/A } else { 10981681SN/A cprintf("dependGraph[%i]: No producer. consumer: ", i); 10991681SN/A } 11001681SN/A 11011681SN/A while (curr->next != NULL) { 11021681SN/A curr = curr->next; 11031681SN/A 11041681SN/A cprintf("%#x ", curr->inst->readPC()); 11051681SN/A } 11061681SN/A 11071681SN/A cprintf("\n"); 11081681SN/A } 11091681SN/A} 11101681SN/A 11111681SN/Atemplate <class Impl> 11121681SN/Avoid 11131061SN/AInstructionQueue<Impl>::dumpLists() 11141061SN/A{ 11151061SN/A cprintf("Ready integer list size: %i\n", readyIntInsts.size()); 11161061SN/A 11171061SN/A cprintf("Ready float list size: %i\n", readyFloatInsts.size()); 11181061SN/A 11191061SN/A cprintf("Ready branch list size: %i\n", readyBranchInsts.size()); 11201061SN/A 11211061SN/A cprintf("Ready misc list size: %i\n", readyMiscInsts.size()); 11221061SN/A 11231061SN/A cprintf("Squashed list size: %i\n", squashedInsts.size()); 11241061SN/A 11251061SN/A cprintf("Non speculative list size: %i\n", nonSpecInsts.size()); 11261061SN/A 11271061SN/A non_spec_it_t non_spec_it = nonSpecInsts.begin(); 11281061SN/A 11291061SN/A cprintf("Non speculative list: "); 11301061SN/A 11311061SN/A while (non_spec_it != nonSpecInsts.end()) { 11321061SN/A cprintf("%#x ", (*non_spec_it).second->readPC()); 11331061SN/A ++non_spec_it; 11341061SN/A } 11351061SN/A 11361061SN/A cprintf("\n"); 11371061SN/A 11381061SN/A} 1139