inst_queue_impl.hh revision 2698:d5f35d41e017
16657Snate@binkert.org/* 26657Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan 36657Snate@binkert.org * All rights reserved. 46657Snate@binkert.org * 56657Snate@binkert.org * Redistribution and use in source and binary forms, with or without 66657Snate@binkert.org * modification, are permitted provided that the following conditions are 76657Snate@binkert.org * met: redistributions of source code must retain the above copyright 86657Snate@binkert.org * notice, this list of conditions and the following disclaimer; 96657Snate@binkert.org * redistributions in binary form must reproduce the above copyright 106657Snate@binkert.org * notice, this list of conditions and the following disclaimer in the 116657Snate@binkert.org * documentation and/or other materials provided with the distribution; 126657Snate@binkert.org * neither the name of the copyright holders nor the names of its 136657Snate@binkert.org * contributors may be used to endorse or promote products derived from 146657Snate@binkert.org * this software without specific prior written permission. 156657Snate@binkert.org * 166657Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 176657Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 186657Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 196657Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 206657Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 216657Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 226657Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 236657Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 246657Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 256657Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 266657Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 276657Snate@binkert.org * 286999Snate@binkert.org * Authors: Kevin Lim 296657Snate@binkert.org */ 306657Snate@binkert.org 316657Snate@binkert.org#include <limits> 326657Snate@binkert.org#include <vector> 336657Snate@binkert.org 346882SBrad.Beckmann@amd.com#include "sim/root.hh" 356882SBrad.Beckmann@amd.com 366882SBrad.Beckmann@amd.com#include "cpu/o3/fu_pool.hh" 376882SBrad.Beckmann@amd.com#include "cpu/o3/inst_queue.hh" 386882SBrad.Beckmann@amd.com 396882SBrad.Beckmann@amd.comusing namespace std; 406882SBrad.Beckmann@amd.com 416888SBrad.Beckmann@amd.comtemplate <class Impl> 426882SBrad.Beckmann@amd.comInstructionQueue<Impl>::FUCompletion::FUCompletion(DynInstPtr &_inst, 436882SBrad.Beckmann@amd.com int fu_idx, 446657Snate@binkert.org InstructionQueue<Impl> *iq_ptr) 456657Snate@binkert.org : Event(&mainEventQueue, Stat_Event_Pri), 466657Snate@binkert.org inst(_inst), fuIdx(fu_idx), iqPtr(iq_ptr), freeFU(false) 476657Snate@binkert.org{ 486657Snate@binkert.org this->setFlags(Event::AutoDelete); 496657Snate@binkert.org} 506882SBrad.Beckmann@amd.com 516882SBrad.Beckmann@amd.comtemplate <class Impl> 526882SBrad.Beckmann@amd.comvoid 536882SBrad.Beckmann@amd.comInstructionQueue<Impl>::FUCompletion::process() 546882SBrad.Beckmann@amd.com{ 556882SBrad.Beckmann@amd.com iqPtr->processFUCompletion(inst, freeFU ? fuIdx : -1); 566657Snate@binkert.org inst = NULL; 576657Snate@binkert.org} 586657Snate@binkert.org 596657Snate@binkert.org 606657Snate@binkert.orgtemplate <class Impl> 616657Snate@binkert.orgconst char * 626657Snate@binkert.orgInstructionQueue<Impl>::FUCompletion::description() 636657Snate@binkert.org{ 646657Snate@binkert.org return "Functional unit completion event"; 656657Snate@binkert.org} 666657Snate@binkert.org 676657Snate@binkert.orgtemplate <class Impl> 686657Snate@binkert.orgInstructionQueue<Impl>::InstructionQueue(Params *params) 696657Snate@binkert.org : fuPool(params->fuPool), 706657Snate@binkert.org numEntries(params->numIQEntries), 716657Snate@binkert.org totalWidth(params->issueWidth), 726657Snate@binkert.org numPhysIntRegs(params->numPhysIntRegs), 736657Snate@binkert.org numPhysFloatRegs(params->numPhysFloatRegs), 746657Snate@binkert.org commitToIEWDelay(params->commitToIEWDelay) 756657Snate@binkert.org{ 766657Snate@binkert.org assert(fuPool); 776657Snate@binkert.org 786657Snate@binkert.org switchedOut = false; 796657Snate@binkert.org 806657Snate@binkert.org numThreads = params->numberOfThreads; 816657Snate@binkert.org 826657Snate@binkert.org // Set the number of physical registers as the number of int + float 836657Snate@binkert.org numPhysRegs = numPhysIntRegs + numPhysFloatRegs; 846657Snate@binkert.org 856779SBrad.Beckmann@amd.com DPRINTF(IQ, "There are %i physical registers.\n", numPhysRegs); 866657Snate@binkert.org 876657Snate@binkert.org //Create an entry for each physical register within the 886657Snate@binkert.org //dependency graph. 896657Snate@binkert.org dependGraph.resize(numPhysRegs); 906657Snate@binkert.org 916657Snate@binkert.org // Resize the register scoreboard. 926657Snate@binkert.org regScoreboard.resize(numPhysRegs); 936657Snate@binkert.org 946657Snate@binkert.org //Initialize Mem Dependence Units 956657Snate@binkert.org for (int i = 0; i < numThreads; i++) { 966657Snate@binkert.org memDepUnit[i].init(params,i); 976657Snate@binkert.org memDepUnit[i].setIQ(this); 986657Snate@binkert.org } 996657Snate@binkert.org 1006657Snate@binkert.org resetState(); 1016657Snate@binkert.org 1026657Snate@binkert.org string policy = params->smtIQPolicy; 1036657Snate@binkert.org 1046657Snate@binkert.org //Convert string to lowercase 1056657Snate@binkert.org std::transform(policy.begin(), policy.end(), policy.begin(), 1066657Snate@binkert.org (int(*)(int)) tolower); 1076657Snate@binkert.org 1086657Snate@binkert.org //Figure out resource sharing policy 1096657Snate@binkert.org if (policy == "dynamic") { 1106657Snate@binkert.org iqPolicy = Dynamic; 1116657Snate@binkert.org 1126657Snate@binkert.org //Set Max Entries to Total ROB Capacity 1136657Snate@binkert.org for (int i = 0; i < numThreads; i++) { 1146657Snate@binkert.org maxEntries[i] = numEntries; 1156657Snate@binkert.org } 1166657Snate@binkert.org 1176657Snate@binkert.org } else if (policy == "partitioned") { 1186657Snate@binkert.org iqPolicy = Partitioned; 1196657Snate@binkert.org 1206657Snate@binkert.org //@todo:make work if part_amt doesnt divide evenly. 1216657Snate@binkert.org int part_amt = numEntries / numThreads; 1226657Snate@binkert.org 1236657Snate@binkert.org //Divide ROB up evenly 1246657Snate@binkert.org for (int i = 0; i < numThreads; i++) { 1256657Snate@binkert.org maxEntries[i] = part_amt; 1266657Snate@binkert.org } 1276657Snate@binkert.org 1286657Snate@binkert.org DPRINTF(Fetch, "IQ sharing policy set to Partitioned:" 1296657Snate@binkert.org "%i entries per thread.\n",part_amt); 1306657Snate@binkert.org 1316657Snate@binkert.org } else if (policy == "threshold") { 1326657Snate@binkert.org iqPolicy = Threshold; 1336657Snate@binkert.org 1346657Snate@binkert.org double threshold = (double)params->smtIQThreshold / 100; 1356657Snate@binkert.org 1366657Snate@binkert.org int thresholdIQ = (int)((double)threshold * numEntries); 1376657Snate@binkert.org 1386657Snate@binkert.org //Divide up by threshold amount 1396657Snate@binkert.org for (int i = 0; i < numThreads; i++) { 1406657Snate@binkert.org maxEntries[i] = thresholdIQ; 1416877Ssteve.reinhardt@amd.com } 1426657Snate@binkert.org 1436657Snate@binkert.org DPRINTF(Fetch, "IQ sharing policy set to Threshold:" 1446657Snate@binkert.org "%i entries per thread.\n",thresholdIQ); 1456657Snate@binkert.org } else { 1466657Snate@binkert.org assert(0 && "Invalid IQ Sharing Policy.Options Are:{Dynamic," 1476657Snate@binkert.org "Partitioned, Threshold}"); 1486657Snate@binkert.org } 1496657Snate@binkert.org} 1506657Snate@binkert.org 1516657Snate@binkert.orgtemplate <class Impl> 1526877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::~InstructionQueue() 1536999Snate@binkert.org{ 1546877Ssteve.reinhardt@amd.com dependGraph.reset(); 1556877Ssteve.reinhardt@amd.com#ifdef DEBUG 1566877Ssteve.reinhardt@amd.com cprintf("Nodes traversed: %i, removed: %i\n", 1576877Ssteve.reinhardt@amd.com dependGraph.nodesTraversed, dependGraph.nodesRemoved); 1586877Ssteve.reinhardt@amd.com#endif 1596877Ssteve.reinhardt@amd.com} 1606877Ssteve.reinhardt@amd.com 1616877Ssteve.reinhardt@amd.comtemplate <class Impl> 1626877Ssteve.reinhardt@amd.comstd::string 1636877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::name() const 1646877Ssteve.reinhardt@amd.com{ 1656877Ssteve.reinhardt@amd.com return cpu->name() + ".iq"; 1666877Ssteve.reinhardt@amd.com} 1676877Ssteve.reinhardt@amd.com 1686877Ssteve.reinhardt@amd.comtemplate <class Impl> 1696877Ssteve.reinhardt@amd.comvoid 1706882SBrad.Beckmann@amd.comInstructionQueue<Impl>::regStats() 1716882SBrad.Beckmann@amd.com{ 1726882SBrad.Beckmann@amd.com using namespace Stats; 1736882SBrad.Beckmann@amd.com iqInstsAdded 1746882SBrad.Beckmann@amd.com .name(name() + ".iqInstsAdded") 1756882SBrad.Beckmann@amd.com .desc("Number of instructions added to the IQ (excludes non-spec)") 1766882SBrad.Beckmann@amd.com .prereq(iqInstsAdded); 1776877Ssteve.reinhardt@amd.com 1786877Ssteve.reinhardt@amd.com iqNonSpecInstsAdded 1796877Ssteve.reinhardt@amd.com .name(name() + ".iqNonSpecInstsAdded") 1806877Ssteve.reinhardt@amd.com .desc("Number of non-speculative instructions added to the IQ") 1816657Snate@binkert.org .prereq(iqNonSpecInstsAdded); 1826657Snate@binkert.org 1836999Snate@binkert.org iqInstsIssued 1846657Snate@binkert.org .name(name() + ".iqInstsIssued") 1856657Snate@binkert.org .desc("Number of instructions issued") 1866657Snate@binkert.org .prereq(iqInstsIssued); 1876657Snate@binkert.org 1886657Snate@binkert.org iqIntInstsIssued 1896657Snate@binkert.org .name(name() + ".iqIntInstsIssued") 1907007Snate@binkert.org .desc("Number of integer instructions issued") 1916657Snate@binkert.org .prereq(iqIntInstsIssued); 1926657Snate@binkert.org 1936657Snate@binkert.org iqFloatInstsIssued 1946657Snate@binkert.org .name(name() + ".iqFloatInstsIssued") 1956657Snate@binkert.org .desc("Number of float instructions issued") 1967007Snate@binkert.org .prereq(iqFloatInstsIssued); 1977007Snate@binkert.org 1986657Snate@binkert.org iqBranchInstsIssued 1997002Snate@binkert.org .name(name() + ".iqBranchInstsIssued") 2007002Snate@binkert.org .desc("Number of branch instructions issued") 2017002Snate@binkert.org .prereq(iqBranchInstsIssued); 2027002Snate@binkert.org 2036877Ssteve.reinhardt@amd.com iqMemInstsIssued 2046877Ssteve.reinhardt@amd.com .name(name() + ".iqMemInstsIssued") 2056657Snate@binkert.org .desc("Number of memory instructions issued") 2066657Snate@binkert.org .prereq(iqMemInstsIssued); 2076657Snate@binkert.org 2086657Snate@binkert.org iqMiscInstsIssued 2096657Snate@binkert.org .name(name() + ".iqMiscInstsIssued") 2106657Snate@binkert.org .desc("Number of miscellaneous instructions issued") 2116657Snate@binkert.org .prereq(iqMiscInstsIssued); 2126657Snate@binkert.org 2136657Snate@binkert.org iqSquashedInstsIssued 2146657Snate@binkert.org .name(name() + ".iqSquashedInstsIssued") 2156793SBrad.Beckmann@amd.com .desc("Number of squashed instructions issued") 2166657Snate@binkert.org .prereq(iqSquashedInstsIssued); 2176657Snate@binkert.org 2186657Snate@binkert.org iqSquashedInstsExamined 2196657Snate@binkert.org .name(name() + ".iqSquashedInstsExamined") 2206657Snate@binkert.org .desc("Number of squashed instructions iterated over during squash;" 2217002Snate@binkert.org " mainly for profiling") 2226657Snate@binkert.org .prereq(iqSquashedInstsExamined); 2237007Snate@binkert.org 2247007Snate@binkert.org iqSquashedOperandsExamined 2257007Snate@binkert.org .name(name() + ".iqSquashedOperandsExamined") 2267007Snate@binkert.org .desc("Number of squashed operands that are examined and possibly " 2277007Snate@binkert.org "removed from graph") 2286657Snate@binkert.org .prereq(iqSquashedOperandsExamined); 2296877Ssteve.reinhardt@amd.com 2306877Ssteve.reinhardt@amd.com iqSquashedNonSpecRemoved 2316657Snate@binkert.org .name(name() + ".iqSquashedNonSpecRemoved") 2326877Ssteve.reinhardt@amd.com .desc("Number of squashed non-spec instructions that were removed") 2336657Snate@binkert.org .prereq(iqSquashedNonSpecRemoved); 2346657Snate@binkert.org 2357002Snate@binkert.org queueResDist 2367002Snate@binkert.org .init(Num_OpClasses, 0, 99, 2) 2376657Snate@binkert.org .name(name() + ".IQ:residence:") 2386881SBrad.Beckmann@amd.com .desc("cycles from dispatch to issue") 2397002Snate@binkert.org .flags(total | pdf | cdf ) 2407002Snate@binkert.org ; 2416657Snate@binkert.org for (int i = 0; i < Num_OpClasses; ++i) { 2427002Snate@binkert.org queueResDist.subname(i, opClassStrings[i]); 2436902SBrad.Beckmann@amd.com } 2446863Sdrh5@cs.wisc.edu numIssuedDist 2456863Sdrh5@cs.wisc.edu .init(0,totalWidth,1) 2467007Snate@binkert.org .name(name() + ".ISSUE:issued_per_cycle") 2476657Snate@binkert.org .desc("Number of insts issued each cycle") 2486657Snate@binkert.org .flags(pdf) 2496657Snate@binkert.org ; 2506657Snate@binkert.org/* 2516657Snate@binkert.org dist_unissued 2526657Snate@binkert.org .init(Num_OpClasses+2) 2536882SBrad.Beckmann@amd.com .name(name() + ".ISSUE:unissued_cause") 2546882SBrad.Beckmann@amd.com .desc("Reason ready instruction not issued") 2556882SBrad.Beckmann@amd.com .flags(pdf | dist) 2566882SBrad.Beckmann@amd.com ; 2576657Snate@binkert.org for (int i=0; i < (Num_OpClasses + 2); ++i) { 2586657Snate@binkert.org dist_unissued.subname(i, unissued_names[i]); 2596657Snate@binkert.org } 2606657Snate@binkert.org*/ 2617007Snate@binkert.org statIssuedInstType 2627007Snate@binkert.org .init(numThreads,Num_OpClasses) 2637007Snate@binkert.org .name(name() + ".ISSUE:FU_type") 2647007Snate@binkert.org .desc("Type of FU issued") 2657007Snate@binkert.org .flags(total | pdf | dist) 2667007Snate@binkert.org ; 2677007Snate@binkert.org statIssuedInstType.ysubnames(opClassStrings); 2687007Snate@binkert.org 2697007Snate@binkert.org // 2707002Snate@binkert.org // How long did instructions for a particular FU type wait prior to issue 2716657Snate@binkert.org // 2726657Snate@binkert.org 2736657Snate@binkert.org issueDelayDist 2747002Snate@binkert.org .init(Num_OpClasses,0,99,2) 2756657Snate@binkert.org .name(name() + ".ISSUE:") 2766657Snate@binkert.org .desc("cycles from operands ready to issue") 2776657Snate@binkert.org .flags(pdf | cdf) 2786863Sdrh5@cs.wisc.edu ; 2796863Sdrh5@cs.wisc.edu 2806657Snate@binkert.org for (int i=0; i<Num_OpClasses; ++i) { 2816657Snate@binkert.org stringstream subname; 2827007Snate@binkert.org subname << opClassStrings[i] << "_delay"; 2836657Snate@binkert.org issueDelayDist.subname(i, subname.str()); 2846657Snate@binkert.org } 2856657Snate@binkert.org 2866657Snate@binkert.org issueRate 2876657Snate@binkert.org .name(name() + ".ISSUE:rate") 2886657Snate@binkert.org .desc("Inst issue rate") 2896657Snate@binkert.org .flags(total) 2906657Snate@binkert.org ; 2916657Snate@binkert.org issueRate = iqInstsIssued / cpu->numCycles; 2926657Snate@binkert.org/* 2936657Snate@binkert.org issue_stores 2946657Snate@binkert.org .name(name() + ".ISSUE:stores") 2956657Snate@binkert.org .desc("Number of stores issued") 2966657Snate@binkert.org .flags(total) 2976657Snate@binkert.org ; 2986657Snate@binkert.org issue_stores = exe_refs - exe_loads; 2996657Snate@binkert.org*/ 3006657Snate@binkert.org/* 3016657Snate@binkert.org issue_op_rate 3027007Snate@binkert.org .name(name() + ".ISSUE:op_rate") 3036657Snate@binkert.org .desc("Operation issue rate") 3046657Snate@binkert.org .flags(total) 3056657Snate@binkert.org ; 3066657Snate@binkert.org issue_op_rate = issued_ops / numCycles; 3076657Snate@binkert.org*/ 3086657Snate@binkert.org statFuBusy 3096657Snate@binkert.org .init(Num_OpClasses) 3106657Snate@binkert.org .name(name() + ".ISSUE:fu_full") 3116657Snate@binkert.org .desc("attempts to use FU when none available") 3126657Snate@binkert.org .flags(pdf | dist) 3137007Snate@binkert.org ; 3146657Snate@binkert.org for (int i=0; i < Num_OpClasses; ++i) { 3156657Snate@binkert.org statFuBusy.subname(i, opClassStrings[i]); 3166657Snate@binkert.org } 3176657Snate@binkert.org 3186657Snate@binkert.org fuBusy 3196999Snate@binkert.org .init(numThreads) 3206657Snate@binkert.org .name(name() + ".ISSUE:fu_busy_cnt") 3216657Snate@binkert.org .desc("FU busy when requested") 3226657Snate@binkert.org .flags(total) 3236657Snate@binkert.org ; 3247007Snate@binkert.org 3256657Snate@binkert.org fuBusyRate 3266657Snate@binkert.org .name(name() + ".ISSUE:fu_busy_rate") 3276657Snate@binkert.org .desc("FU busy rate (busy events/executed inst)") 3286657Snate@binkert.org .flags(total) 3296657Snate@binkert.org ; 3307002Snate@binkert.org fuBusyRate = fuBusy / iqInstsIssued; 3317002Snate@binkert.org 3327002Snate@binkert.org for ( int i=0; i < numThreads; i++) { 3336657Snate@binkert.org // Tell mem dependence unit to reg stats as well. 3346657Snate@binkert.org memDepUnit[i].regStats(); 3356657Snate@binkert.org } 3366657Snate@binkert.org} 3376657Snate@binkert.org 3386657Snate@binkert.orgtemplate <class Impl> 3396657Snate@binkert.orgvoid 3407002Snate@binkert.orgInstructionQueue<Impl>::resetState() 3417002Snate@binkert.org{ 3426657Snate@binkert.org //Initialize thread IQ counts 3436657Snate@binkert.org for (int i = 0; i <numThreads; i++) { 3446657Snate@binkert.org count[i] = 0; 3456657Snate@binkert.org instList[i].clear(); 3466657Snate@binkert.org } 3476793SBrad.Beckmann@amd.com 3486657Snate@binkert.org // Initialize the number of free IQ entries. 3496657Snate@binkert.org freeEntries = numEntries; 3506657Snate@binkert.org 3516657Snate@binkert.org // Note that in actuality, the registers corresponding to the logical 3526877Ssteve.reinhardt@amd.com // registers start off as ready. However this doesn't matter for the 3536877Ssteve.reinhardt@amd.com // IQ as the instruction should have been correctly told if those 3546877Ssteve.reinhardt@amd.com // registers are ready in rename. Thus it can all be initialized as 3556877Ssteve.reinhardt@amd.com // unready. 3566877Ssteve.reinhardt@amd.com for (int i = 0; i < numPhysRegs; ++i) { 3576877Ssteve.reinhardt@amd.com regScoreboard[i] = false; 3586657Snate@binkert.org } 3596657Snate@binkert.org 3607007Snate@binkert.org for (int i = 0; i < numThreads; ++i) { 3616657Snate@binkert.org squashedSeqNum[i] = 0; 3626657Snate@binkert.org } 3637007Snate@binkert.org 3646657Snate@binkert.org for (int i = 0; i < Num_OpClasses; ++i) { 3656877Ssteve.reinhardt@amd.com while (!readyInsts[i].empty()) 3666877Ssteve.reinhardt@amd.com readyInsts[i].pop(); 3676657Snate@binkert.org queueOnList[i] = false; 3686877Ssteve.reinhardt@amd.com readyIt[i] = listOrder.end(); 3696877Ssteve.reinhardt@amd.com } 3706877Ssteve.reinhardt@amd.com nonSpecInsts.clear(); 3716877Ssteve.reinhardt@amd.com listOrder.clear(); 3726877Ssteve.reinhardt@amd.com} 3736969SBrad.Beckmann@amd.com 3746657Snate@binkert.orgtemplate <class Impl> 3756657Snate@binkert.orgvoid 3766882SBrad.Beckmann@amd.comInstructionQueue<Impl>::setActiveThreads(list<unsigned> *at_ptr) 3776882SBrad.Beckmann@amd.com{ 3786882SBrad.Beckmann@amd.com DPRINTF(IQ, "Setting active threads list pointer.\n"); 3796882SBrad.Beckmann@amd.com activeThreads = at_ptr; 3806882SBrad.Beckmann@amd.com} 3816882SBrad.Beckmann@amd.com 3826882SBrad.Beckmann@amd.comtemplate <class Impl> 3836882SBrad.Beckmann@amd.comvoid 3846877Ssteve.reinhardt@amd.comInstructionQueue<Impl>::setIssueToExecuteQueue(TimeBuffer<IssueStruct> *i2e_ptr) 3856888SBrad.Beckmann@amd.com{ 3866882SBrad.Beckmann@amd.com DPRINTF(IQ, "Set the issue to execute queue.\n"); 3876882SBrad.Beckmann@amd.com issueToExecuteQueue = i2e_ptr; 3886882SBrad.Beckmann@amd.com} 3896882SBrad.Beckmann@amd.com 3906882SBrad.Beckmann@amd.comtemplate <class Impl> 3916882SBrad.Beckmann@amd.comvoid 3926882SBrad.Beckmann@amd.comInstructionQueue<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 3936882SBrad.Beckmann@amd.com{ 3946882SBrad.Beckmann@amd.com DPRINTF(IQ, "Set the time buffer.\n"); 3956882SBrad.Beckmann@amd.com timeBuffer = tb_ptr; 3966882SBrad.Beckmann@amd.com 3976882SBrad.Beckmann@amd.com fromCommit = timeBuffer->getWire(-commitToIEWDelay); 3986882SBrad.Beckmann@amd.com} 3996882SBrad.Beckmann@amd.com 4006882SBrad.Beckmann@amd.comtemplate <class Impl> 4016882SBrad.Beckmann@amd.comvoid 4026882SBrad.Beckmann@amd.comInstructionQueue<Impl>::switchOut() 4036882SBrad.Beckmann@amd.com{ 4046888SBrad.Beckmann@amd.com resetState(); 4056888SBrad.Beckmann@amd.com dependGraph.reset(); 4066888SBrad.Beckmann@amd.com switchedOut = true; 4076888SBrad.Beckmann@amd.com for (int i = 0; i < numThreads; ++i) { 4086888SBrad.Beckmann@amd.com memDepUnit[i].switchOut(); 4096888SBrad.Beckmann@amd.com } 4106888SBrad.Beckmann@amd.com} 4116888SBrad.Beckmann@amd.com 4126657Snate@binkert.orgtemplate <class Impl> 4136888SBrad.Beckmann@amd.comvoid 4146888SBrad.Beckmann@amd.comInstructionQueue<Impl>::takeOverFrom() 4156888SBrad.Beckmann@amd.com{ 4166888SBrad.Beckmann@amd.com switchedOut = false; 4176657Snate@binkert.org} 4186657Snate@binkert.org 4196657Snate@binkert.orgtemplate <class Impl> 4206657Snate@binkert.orgint 4216657Snate@binkert.orgInstructionQueue<Impl>::entryAmount(int num_threads) 4226657Snate@binkert.org{ 4236657Snate@binkert.org if (iqPolicy == Partitioned) { 4246657Snate@binkert.org return numEntries / num_threads; 4256657Snate@binkert.org } else { 4267007Snate@binkert.org return 0; 4277007Snate@binkert.org } 4286657Snate@binkert.org} 4297007Snate@binkert.org 4307007Snate@binkert.org 4317007Snate@binkert.orgtemplate <class Impl> 4326657Snate@binkert.orgvoid 4336657Snate@binkert.orgInstructionQueue<Impl>::resetEntries() 4346657Snate@binkert.org{ 4357007Snate@binkert.org if (iqPolicy != Dynamic || numThreads > 1) { 4366657Snate@binkert.org int active_threads = (*activeThreads).size(); 4377007Snate@binkert.org 4386657Snate@binkert.org list<unsigned>::iterator threads = (*activeThreads).begin(); 4396657Snate@binkert.org list<unsigned>::iterator list_end = (*activeThreads).end(); 4406657Snate@binkert.org 4416657Snate@binkert.org while (threads != list_end) { 4426657Snate@binkert.org if (iqPolicy == Partitioned) { 4436657Snate@binkert.org maxEntries[*threads++] = numEntries / active_threads; 4446657Snate@binkert.org } else if(iqPolicy == Threshold && active_threads == 1) { 4456657Snate@binkert.org maxEntries[*threads++] = numEntries; 4466657Snate@binkert.org } 4476657Snate@binkert.org } 4486657Snate@binkert.org } 4496657Snate@binkert.org} 4506657Snate@binkert.org 4516657Snate@binkert.orgtemplate <class Impl> 4526657Snate@binkert.orgunsigned 4536657Snate@binkert.orgInstructionQueue<Impl>::numFreeEntries() 4546657Snate@binkert.org{ 4556657Snate@binkert.org return freeEntries; 4566657Snate@binkert.org} 4576657Snate@binkert.org 4586657Snate@binkert.orgtemplate <class Impl> 4596657Snate@binkert.orgunsigned 4606657Snate@binkert.orgInstructionQueue<Impl>::numFreeEntries(unsigned tid) 4616657Snate@binkert.org{ 4626657Snate@binkert.org return maxEntries[tid] - count[tid]; 4636657Snate@binkert.org} 4646657Snate@binkert.org 4656657Snate@binkert.org// Might want to do something more complex if it knows how many instructions 4667007Snate@binkert.org// will be issued this cycle. 4676657Snate@binkert.orgtemplate <class Impl> 4686657Snate@binkert.orgbool 4696657Snate@binkert.orgInstructionQueue<Impl>::isFull() 4706657Snate@binkert.org{ 4717007Snate@binkert.org if (freeEntries == 0) { 4726657Snate@binkert.org return(true); 4737007Snate@binkert.org } else { 4747007Snate@binkert.org return(false); 4756657Snate@binkert.org } 4766657Snate@binkert.org} 4776657Snate@binkert.org 4786657Snate@binkert.orgtemplate <class Impl> 4796657Snate@binkert.orgbool 4806657Snate@binkert.orgInstructionQueue<Impl>::isFull(unsigned tid) 4816657Snate@binkert.org{ 4826657Snate@binkert.org if (numFreeEntries(tid) == 0) { 4836657Snate@binkert.org return(true); 4846657Snate@binkert.org } else { 4856657Snate@binkert.org return(false); 4866657Snate@binkert.org } 4876657Snate@binkert.org} 4886657Snate@binkert.org 4896657Snate@binkert.orgtemplate <class Impl> 4906657Snate@binkert.orgbool 4916657Snate@binkert.orgInstructionQueue<Impl>::hasReadyInsts() 4926657Snate@binkert.org{ 4936657Snate@binkert.org if (!listOrder.empty()) { 4946657Snate@binkert.org return true; 4956657Snate@binkert.org } 4966657Snate@binkert.org 4976657Snate@binkert.org for (int i = 0; i < Num_OpClasses; ++i) { 4987007Snate@binkert.org if (!readyInsts[i].empty()) { 4997007Snate@binkert.org return true; 5007007Snate@binkert.org } 5016657Snate@binkert.org } 5026657Snate@binkert.org 5036657Snate@binkert.org return false; 5046657Snate@binkert.org} 5056657Snate@binkert.org 5066657Snate@binkert.orgtemplate <class Impl> 5076657Snate@binkert.orgvoid 5086657Snate@binkert.orgInstructionQueue<Impl>::insert(DynInstPtr &new_inst) 5096657Snate@binkert.org{ 5106657Snate@binkert.org // Make sure the instruction is valid 5116657Snate@binkert.org assert(new_inst); 5126657Snate@binkert.org 5136657Snate@binkert.org DPRINTF(IQ, "Adding instruction [sn:%lli] PC %#x to the IQ.\n", 5146657Snate@binkert.org new_inst->seqNum, new_inst->readPC()); 5156657Snate@binkert.org 5166657Snate@binkert.org assert(freeEntries != 0); 5176657Snate@binkert.org 5186657Snate@binkert.org instList[new_inst->threadNumber].push_back(new_inst); 5196657Snate@binkert.org 5206657Snate@binkert.org --freeEntries; 5216657Snate@binkert.org 5226657Snate@binkert.org new_inst->setInIQ(); 5236657Snate@binkert.org 5246657Snate@binkert.org // Look through its source registers (physical regs), and mark any 5256657Snate@binkert.org // dependencies. 5266657Snate@binkert.org addToDependents(new_inst); 5276657Snate@binkert.org 5287007Snate@binkert.org // Have this instruction set itself as the producer of its destination 5297007Snate@binkert.org // register(s). 5307007Snate@binkert.org addToProducers(new_inst); 5317007Snate@binkert.org 5326657Snate@binkert.org if (new_inst->isMemRef()) { 5336657Snate@binkert.org memDepUnit[new_inst->threadNumber].insert(new_inst); 5346657Snate@binkert.org } else { 5356657Snate@binkert.org addIfReady(new_inst); 5366657Snate@binkert.org } 5376657Snate@binkert.org 5386657Snate@binkert.org ++iqInstsAdded; 5396657Snate@binkert.org 5406657Snate@binkert.org count[new_inst->threadNumber]++; 5416657Snate@binkert.org 5426657Snate@binkert.org assert(freeEntries == (numEntries - countInsts())); 5436657Snate@binkert.org} 5446657Snate@binkert.org 5456657Snate@binkert.orgtemplate <class Impl> 5466657Snate@binkert.orgvoid 5476657Snate@binkert.orgInstructionQueue<Impl>::insertNonSpec(DynInstPtr &new_inst) 5486657Snate@binkert.org{ 5496657Snate@binkert.org // @todo: Clean up this code; can do it by setting inst as unable 5506657Snate@binkert.org // to issue, then calling normal insert on the inst. 5516657Snate@binkert.org 5526657Snate@binkert.org assert(new_inst); 5536657Snate@binkert.org 5546657Snate@binkert.org nonSpecInsts[new_inst->seqNum] = new_inst; 5556657Snate@binkert.org 5566657Snate@binkert.org DPRINTF(IQ, "Adding non-speculative instruction [sn:%lli] PC %#x " 5576657Snate@binkert.org "to the IQ.\n", 5586657Snate@binkert.org new_inst->seqNum, new_inst->readPC()); 5596657Snate@binkert.org 5606657Snate@binkert.org assert(freeEntries != 0); 5616657Snate@binkert.org 5626657Snate@binkert.org instList[new_inst->threadNumber].push_back(new_inst); 5636657Snate@binkert.org 5646657Snate@binkert.org --freeEntries; 5656657Snate@binkert.org 5666657Snate@binkert.org new_inst->setInIQ(); 5676657Snate@binkert.org 5686657Snate@binkert.org // Have this instruction set itself as the producer of its destination 5696657Snate@binkert.org // register(s). 5706657Snate@binkert.org addToProducers(new_inst); 5716657Snate@binkert.org 5726657Snate@binkert.org // If it's a memory instruction, add it to the memory dependency 5736657Snate@binkert.org // unit. 5746657Snate@binkert.org if (new_inst->isMemRef()) { 5756657Snate@binkert.org memDepUnit[new_inst->threadNumber].insertNonSpec(new_inst); 5767007Snate@binkert.org } 5777007Snate@binkert.org 5787007Snate@binkert.org ++iqNonSpecInstsAdded; 5796657Snate@binkert.org 5806657Snate@binkert.org count[new_inst->threadNumber]++; 5816657Snate@binkert.org 5827007Snate@binkert.org assert(freeEntries == (numEntries - countInsts())); 5837007Snate@binkert.org} 5847007Snate@binkert.org 5856657Snate@binkert.orgtemplate <class Impl> 5866657Snate@binkert.orgvoid 5876657Snate@binkert.orgInstructionQueue<Impl>::insertBarrier(DynInstPtr &barr_inst) 5887007Snate@binkert.org{ 5897007Snate@binkert.org memDepUnit[barr_inst->threadNumber].insertBarrier(barr_inst); 5907007Snate@binkert.org 5916657Snate@binkert.org insertNonSpec(barr_inst); 5926657Snate@binkert.org} 5936657Snate@binkert.org 5947007Snate@binkert.orgtemplate <class Impl> 5957007Snate@binkert.orgtypename Impl::DynInstPtr 5967007Snate@binkert.orgInstructionQueue<Impl>::getInstToExecute() 5976657Snate@binkert.org{ 5986657Snate@binkert.org assert(!instsToExecute.empty()); 5996657Snate@binkert.org DynInstPtr inst = instsToExecute.front(); 6007007Snate@binkert.org instsToExecute.pop_front(); 6017007Snate@binkert.org return inst; 6027007Snate@binkert.org} 6036657Snate@binkert.org 6046657Snate@binkert.orgtemplate <class Impl> 6057007Snate@binkert.orgvoid 6067007Snate@binkert.orgInstructionQueue<Impl>::addToOrderList(OpClass op_class) 6077007Snate@binkert.org{ 6087007Snate@binkert.org assert(!readyInsts[op_class].empty()); 6096657Snate@binkert.org 6106657Snate@binkert.org ListOrderEntry queue_entry; 6116657Snate@binkert.org 6127007Snate@binkert.org queue_entry.queueType = op_class; 6137007Snate@binkert.org 6147007Snate@binkert.org queue_entry.oldestInst = readyInsts[op_class].top()->seqNum; 6156863Sdrh5@cs.wisc.edu 6166863Sdrh5@cs.wisc.edu ListOrderIt list_it = listOrder.begin(); 6176863Sdrh5@cs.wisc.edu ListOrderIt list_end_it = listOrder.end(); 6187007Snate@binkert.org 6197007Snate@binkert.org while (list_it != list_end_it) { 6207007Snate@binkert.org if ((*list_it).oldestInst > queue_entry.oldestInst) { 6217007Snate@binkert.org break; 6226863Sdrh5@cs.wisc.edu } 6236863Sdrh5@cs.wisc.edu 6246863Sdrh5@cs.wisc.edu list_it++; 6256863Sdrh5@cs.wisc.edu } 6266863Sdrh5@cs.wisc.edu 6276863Sdrh5@cs.wisc.edu readyIt[op_class] = listOrder.insert(list_it, queue_entry); 6287007Snate@binkert.org queueOnList[op_class] = true; 6297007Snate@binkert.org} 6307007Snate@binkert.org 6317007Snate@binkert.orgtemplate <class Impl> 6327007Snate@binkert.orgvoid 6336657Snate@binkert.orgInstructionQueue<Impl>::moveToYoungerInst(ListOrderIt list_order_it) 6347007Snate@binkert.org{ 6357007Snate@binkert.org // Get iterator of next item on the list 6367007Snate@binkert.org // Delete the original iterator 6376657Snate@binkert.org // Determine if the next item is either the end of the list or younger 6386657Snate@binkert.org // than the new instruction. If so, then add in a new iterator right here. 6397007Snate@binkert.org // If not, then move along. 6407007Snate@binkert.org ListOrderEntry queue_entry; 6417007Snate@binkert.org OpClass op_class = (*list_order_it).queueType; 6426657Snate@binkert.org ListOrderIt next_it = list_order_it; 6436657Snate@binkert.org 6447007Snate@binkert.org ++next_it; 6457007Snate@binkert.org 6467007Snate@binkert.org queue_entry.queueType = op_class; 6476902SBrad.Beckmann@amd.com queue_entry.oldestInst = readyInsts[op_class].top()->seqNum; 6486902SBrad.Beckmann@amd.com 6496902SBrad.Beckmann@amd.com while (next_it != listOrder.end() && 6506902SBrad.Beckmann@amd.com (*next_it).oldestInst < queue_entry.oldestInst) { 6516902SBrad.Beckmann@amd.com ++next_it; 6526902SBrad.Beckmann@amd.com } 6536902SBrad.Beckmann@amd.com 6546902SBrad.Beckmann@amd.com readyIt[op_class] = listOrder.insert(next_it, queue_entry); 6556902SBrad.Beckmann@amd.com} 6566902SBrad.Beckmann@amd.com 6576902SBrad.Beckmann@amd.comtemplate <class Impl> 6586902SBrad.Beckmann@amd.comvoid 6596902SBrad.Beckmann@amd.comInstructionQueue<Impl>::processFUCompletion(DynInstPtr &inst, int fu_idx) 6606902SBrad.Beckmann@amd.com{ 6616902SBrad.Beckmann@amd.com // The CPU could have been sleeping until this op completed (*extremely* 6626902SBrad.Beckmann@amd.com // long latency op). Wake it if it was. This may be overkill. 6636902SBrad.Beckmann@amd.com if (isSwitchedOut()) { 6646902SBrad.Beckmann@amd.com return; 6656902SBrad.Beckmann@amd.com } 6666902SBrad.Beckmann@amd.com 6676902SBrad.Beckmann@amd.com iewStage->wakeCPU(); 6686902SBrad.Beckmann@amd.com 6696902SBrad.Beckmann@amd.com if (fu_idx > -1) 6706902SBrad.Beckmann@amd.com fuPool->freeUnitNextCycle(fu_idx); 6716902SBrad.Beckmann@amd.com 6726902SBrad.Beckmann@amd.com // @todo: Ensure that these FU Completions happen at the beginning 6736902SBrad.Beckmann@amd.com // of a cycle, otherwise they could add too many instructions to 6746902SBrad.Beckmann@amd.com // the queue. 6756902SBrad.Beckmann@amd.com issueToExecuteQueue->access(0)->size++; 6766902SBrad.Beckmann@amd.com instsToExecute.push_back(inst); 6776902SBrad.Beckmann@amd.com} 6786657Snate@binkert.org 6796657Snate@binkert.org// @todo: Figure out a better way to remove the squashed items from the 6806657Snate@binkert.org// lists. Checking the top item of each list to see if it's squashed 6816657Snate@binkert.org// wastes time and forces jumps. 6826657Snate@binkert.orgtemplate <class Impl> 6836657Snate@binkert.orgvoid 6846657Snate@binkert.orgInstructionQueue<Impl>::scheduleReadyInsts() 6856657Snate@binkert.org{ 6866657Snate@binkert.org DPRINTF(IQ, "Attempting to schedule ready instructions from " 6877007Snate@binkert.org "the IQ.\n"); 6887007Snate@binkert.org 6896657Snate@binkert.org IssueStruct *i2e_info = issueToExecuteQueue->access(0); 6906657Snate@binkert.org 6916657Snate@binkert.org // Have iterator to head of the list 6926657Snate@binkert.org // While I haven't exceeded bandwidth or reached the end of the list, 6936657Snate@binkert.org // Try to get a FU that can do what this op needs. 6946657Snate@binkert.org // If successful, change the oldestInst to the new top of the list, put 6956657Snate@binkert.org // the queue in the proper place in the list. 6966657Snate@binkert.org // Increment the iterator. 6976657Snate@binkert.org // This will avoid trying to schedule a certain op class if there are no 6986657Snate@binkert.org // FUs that handle it. 6996657Snate@binkert.org ListOrderIt order_it = listOrder.begin(); 7006999Snate@binkert.org ListOrderIt order_end_it = listOrder.end(); 7016657Snate@binkert.org int total_issued = 0; 7026657Snate@binkert.org 7036657Snate@binkert.org while (total_issued < totalWidth && 7046657Snate@binkert.org order_it != order_end_it) { 7056657Snate@binkert.org OpClass op_class = (*order_it).queueType; 7066657Snate@binkert.org 7077007Snate@binkert.org assert(!readyInsts[op_class].empty()); 7086657Snate@binkert.org 7096657Snate@binkert.org DynInstPtr issuing_inst = readyInsts[op_class].top(); 7106657Snate@binkert.org 7116657Snate@binkert.org assert(issuing_inst->seqNum == (*order_it).oldestInst); 7126657Snate@binkert.org 7136657Snate@binkert.org if (issuing_inst->isSquashed()) { 7146657Snate@binkert.org readyInsts[op_class].pop(); 7156657Snate@binkert.org 7167007Snate@binkert.org if (!readyInsts[op_class].empty()) { 7177007Snate@binkert.org moveToYoungerInst(order_it); 7186657Snate@binkert.org } else { 7197007Snate@binkert.org readyIt[op_class] = listOrder.end(); 7207007Snate@binkert.org queueOnList[op_class] = false; 7216657Snate@binkert.org } 7226657Snate@binkert.org 7236657Snate@binkert.org listOrder.erase(order_it++); 7246657Snate@binkert.org 7256657Snate@binkert.org ++iqSquashedInstsIssued; 7266657Snate@binkert.org 7277007Snate@binkert.org continue; 7287007Snate@binkert.org } 7297007Snate@binkert.org 7307007Snate@binkert.org int idx = -2; 7317007Snate@binkert.org int op_latency = 1; 7326657Snate@binkert.org int tid = issuing_inst->threadNumber; 7336657Snate@binkert.org 7346657Snate@binkert.org if (op_class != No_OpClass) { 7356657Snate@binkert.org idx = fuPool->getUnit(op_class); 7366657Snate@binkert.org 7376657Snate@binkert.org if (idx > -1) { 7386657Snate@binkert.org op_latency = fuPool->getOpLatency(op_class); 7396657Snate@binkert.org } 7406657Snate@binkert.org } 7416657Snate@binkert.org 7426657Snate@binkert.org // If we have an instruction that doesn't require a FU, or a 7436657Snate@binkert.org // valid FU, then schedule for execution. 7446657Snate@binkert.org if (idx == -2 || idx != -1) { 7456657Snate@binkert.org if (op_latency == 1) { 7466657Snate@binkert.org i2e_info->size++; 7476657Snate@binkert.org instsToExecute.push_back(issuing_inst); 7486657Snate@binkert.org 7496657Snate@binkert.org // Add the FU onto the list of FU's to be freed next 7506657Snate@binkert.org // cycle if we used one. 7516657Snate@binkert.org if (idx >= 0) 7526657Snate@binkert.org fuPool->freeUnitNextCycle(idx); 7536657Snate@binkert.org } else { 7547007Snate@binkert.org int issue_latency = fuPool->getIssueLatency(op_class); 7557007Snate@binkert.org // Generate completion event for the FU 7566657Snate@binkert.org FUCompletion *execution = new FUCompletion(issuing_inst, 7576657Snate@binkert.org idx, this); 7586657Snate@binkert.org 7596657Snate@binkert.org execution->schedule(curTick + cpu->cycles(issue_latency - 1)); 7606657Snate@binkert.org 7616657Snate@binkert.org // @todo: Enforce that issue_latency == 1 or op_latency 7626657Snate@binkert.org if (issue_latency > 1) { 7636657Snate@binkert.org // If FU isn't pipelined, then it must be freed 7646999Snate@binkert.org // upon the execution completing. 7656657Snate@binkert.org execution->setFreeFU(); 7666657Snate@binkert.org } else { 7676657Snate@binkert.org // Add the FU onto the list of FU's to be freed next cycle. 7686657Snate@binkert.org fuPool->freeUnitNextCycle(idx); 7696657Snate@binkert.org } 7706657Snate@binkert.org } 7716657Snate@binkert.org 7726657Snate@binkert.org DPRINTF(IQ, "Thread %i: Issuing instruction PC %#x " 7736657Snate@binkert.org "[sn:%lli]\n", 7746657Snate@binkert.org tid, issuing_inst->readPC(), 7756657Snate@binkert.org issuing_inst->seqNum); 7766657Snate@binkert.org 7776657Snate@binkert.org readyInsts[op_class].pop(); 7786657Snate@binkert.org 7796657Snate@binkert.org if (!readyInsts[op_class].empty()) { 7806657Snate@binkert.org moveToYoungerInst(order_it); 7816657Snate@binkert.org } else { 7826657Snate@binkert.org readyIt[op_class] = listOrder.end(); 7837007Snate@binkert.org queueOnList[op_class] = false; 7847007Snate@binkert.org } 7857007Snate@binkert.org 7867007Snate@binkert.org issuing_inst->setIssued(); 7876657Snate@binkert.org ++total_issued; 7886657Snate@binkert.org 7896657Snate@binkert.org if (!issuing_inst->isMemRef()) { 7906657Snate@binkert.org // Memory instructions can not be freed from the IQ until they 7916657Snate@binkert.org // complete. 7926657Snate@binkert.org ++freeEntries; 7936657Snate@binkert.org count[tid]--; 7946657Snate@binkert.org issuing_inst->removeInIQ(); 7956657Snate@binkert.org } else { 7966657Snate@binkert.org memDepUnit[tid].issue(issuing_inst); 7977007Snate@binkert.org } 7987007Snate@binkert.org 7996657Snate@binkert.org listOrder.erase(order_it++); 8006657Snate@binkert.org statIssuedInstType[tid][op_class]++; 8016657Snate@binkert.org } else { 8026657Snate@binkert.org statFuBusy[op_class]++; 8036657Snate@binkert.org fuBusy[tid]++; 8046657Snate@binkert.org ++order_it; 8057007Snate@binkert.org } 8067007Snate@binkert.org } 8076657Snate@binkert.org 8086657Snate@binkert.org numIssuedDist.sample(total_issued); 8097007Snate@binkert.org iqInstsIssued+= total_issued; 8107007Snate@binkert.org 8116657Snate@binkert.org // If we issued any instructions, tell the CPU we had activity. 8126657Snate@binkert.org if (total_issued) { 8136657Snate@binkert.org cpu->activityThisCycle(); 8146657Snate@binkert.org } else { 8156657Snate@binkert.org DPRINTF(IQ, "Not able to schedule any instructions.\n"); 8166657Snate@binkert.org } 8177007Snate@binkert.org} 8187007Snate@binkert.org 8196657Snate@binkert.orgtemplate <class Impl> 8206657Snate@binkert.orgvoid 8216657Snate@binkert.orgInstructionQueue<Impl>::scheduleNonSpec(const InstSeqNum &inst) 8226657Snate@binkert.org{ 8236657Snate@binkert.org DPRINTF(IQ, "Marking nonspeculative instruction [sn:%lli] as ready " 8246657Snate@binkert.org "to execute.\n", inst); 8256657Snate@binkert.org 8266657Snate@binkert.org NonSpecMapIt inst_it = nonSpecInsts.find(inst); 8276657Snate@binkert.org 8287007Snate@binkert.org assert(inst_it != nonSpecInsts.end()); 8297007Snate@binkert.org 8306657Snate@binkert.org unsigned tid = (*inst_it).second->threadNumber; 8316657Snate@binkert.org 8326657Snate@binkert.org (*inst_it).second->setCanIssue(); 8336657Snate@binkert.org 8346657Snate@binkert.org if (!(*inst_it).second->isMemRef()) { 8356657Snate@binkert.org addIfReady((*inst_it).second); 8366657Snate@binkert.org } else { 8376657Snate@binkert.org memDepUnit[tid].nonSpecInstReady((*inst_it).second); 8386657Snate@binkert.org } 8396657Snate@binkert.org 8407007Snate@binkert.org (*inst_it).second = NULL; 8417007Snate@binkert.org 8427007Snate@binkert.org nonSpecInsts.erase(inst_it); 8437007Snate@binkert.org} 8447007Snate@binkert.org 8456657Snate@binkert.orgtemplate <class Impl> 8466657Snate@binkert.orgvoid 8476657Snate@binkert.orgInstructionQueue<Impl>::commit(const InstSeqNum &inst, unsigned tid) 8486657Snate@binkert.org{ 8496657Snate@binkert.org DPRINTF(IQ, "[tid:%i]: Committing instructions older than [sn:%i]\n", 8506657Snate@binkert.org tid,inst); 8516657Snate@binkert.org 8526657Snate@binkert.org ListIt iq_it = instList[tid].begin(); 8536657Snate@binkert.org 8546657Snate@binkert.org while (iq_it != instList[tid].end() && 8556657Snate@binkert.org (*iq_it)->seqNum <= inst) { 8566999Snate@binkert.org ++iq_it; 8576657Snate@binkert.org instList[tid].pop_front(); 8586657Snate@binkert.org } 8596657Snate@binkert.org 8606657Snate@binkert.org assert(freeEntries == (numEntries - countInsts())); 8616657Snate@binkert.org} 8626657Snate@binkert.org 8636657Snate@binkert.orgtemplate <class Impl> 8646657Snate@binkert.orgint 8656657Snate@binkert.orgInstructionQueue<Impl>::wakeDependents(DynInstPtr &completed_inst) 8666657Snate@binkert.org{ 8676657Snate@binkert.org int dependents = 0; 8686657Snate@binkert.org 8696657Snate@binkert.org DPRINTF(IQ, "Waking dependents of completed instruction.\n"); 8707007Snate@binkert.org 8716657Snate@binkert.org assert(!completed_inst->isSquashed()); 8726657Snate@binkert.org 8736657Snate@binkert.org // Tell the memory dependence unit to wake any dependents on this 8746657Snate@binkert.org // instruction if it is a memory instruction. Also complete the memory 8756657Snate@binkert.org // instruction at this point since we know it executed without issues. 8766657Snate@binkert.org // @todo: Might want to rename "completeMemInst" to something that 8776657Snate@binkert.org // indicates that it won't need to be replayed, and call this 8786657Snate@binkert.org // earlier. Might not be a big deal. 8796657Snate@binkert.org if (completed_inst->isMemRef()) { 8806657Snate@binkert.org memDepUnit[completed_inst->threadNumber].wakeDependents(completed_inst); 8816657Snate@binkert.org completeMemInst(completed_inst); 8826657Snate@binkert.org } else if (completed_inst->isMemBarrier() || 8836657Snate@binkert.org completed_inst->isWriteBarrier()) { 8846657Snate@binkert.org memDepUnit[completed_inst->threadNumber].completeBarrier(completed_inst); 8856657Snate@binkert.org } 8866657Snate@binkert.org 8876657Snate@binkert.org for (int dest_reg_idx = 0; 8886657Snate@binkert.org dest_reg_idx < completed_inst->numDestRegs(); 8896657Snate@binkert.org dest_reg_idx++) 8906657Snate@binkert.org { 8916657Snate@binkert.org PhysRegIndex dest_reg = 8926657Snate@binkert.org completed_inst->renamedDestRegIdx(dest_reg_idx); 8936657Snate@binkert.org 8946657Snate@binkert.org // Special case of uniq or control registers. They are not 8956657Snate@binkert.org // handled by the IQ and thus have no dependency graph entry. 8966657Snate@binkert.org // @todo Figure out a cleaner way to handle this. 8976657Snate@binkert.org if (dest_reg >= numPhysRegs) { 8986657Snate@binkert.org continue; 8996657Snate@binkert.org } 9006657Snate@binkert.org 9016657Snate@binkert.org DPRINTF(IQ, "Waking any dependents on register %i.\n", 9026657Snate@binkert.org (int) dest_reg); 9036657Snate@binkert.org 9046657Snate@binkert.org //Go through the dependency chain, marking the registers as 9056657Snate@binkert.org //ready within the waiting instructions. 9066657Snate@binkert.org DynInstPtr dep_inst = dependGraph.pop(dest_reg); 9076657Snate@binkert.org 9086657Snate@binkert.org while (dep_inst) { 9096657Snate@binkert.org DPRINTF(IQ, "Waking up a dependent instruction, PC%#x.\n", 9106657Snate@binkert.org dep_inst->readPC()); 9116657Snate@binkert.org 9126657Snate@binkert.org // Might want to give more information to the instruction 9136657Snate@binkert.org // so that it knows which of its source registers is 9146657Snate@binkert.org // ready. However that would mean that the dependency 9156657Snate@binkert.org // graph entries would need to hold the src_reg_idx. 9166657Snate@binkert.org dep_inst->markSrcRegReady(); 9176657Snate@binkert.org 9186657Snate@binkert.org addIfReady(dep_inst); 9196657Snate@binkert.org 9206657Snate@binkert.org dep_inst = dependGraph.pop(dest_reg); 9216657Snate@binkert.org 9226657Snate@binkert.org ++dependents; 9236657Snate@binkert.org } 9246657Snate@binkert.org 9256657Snate@binkert.org // Reset the head node now that all of its dependents have 9266657Snate@binkert.org // been woken up. 9276657Snate@binkert.org assert(dependGraph.empty(dest_reg)); 9286999Snate@binkert.org dependGraph.clearInst(dest_reg); 9296657Snate@binkert.org 9306657Snate@binkert.org // Mark the scoreboard as having that register ready. 9316657Snate@binkert.org regScoreboard[dest_reg] = true; 9326657Snate@binkert.org } 9336657Snate@binkert.org return dependents; 9346657Snate@binkert.org} 9357007Snate@binkert.org 9367007Snate@binkert.orgtemplate <class Impl> 9376657Snate@binkert.orgvoid 9387002Snate@binkert.orgInstructionQueue<Impl>::addReadyMemInst(DynInstPtr &ready_inst) 9397002Snate@binkert.org{ 9406657Snate@binkert.org OpClass op_class = ready_inst->opClass(); 9416657Snate@binkert.org 9426657Snate@binkert.org readyInsts[op_class].push(ready_inst); 9436657Snate@binkert.org 9447007Snate@binkert.org // Will need to reorder the list if either a queue is not on the list, 9457007Snate@binkert.org // or it has an older instruction than last time. 9466657Snate@binkert.org if (!queueOnList[op_class]) { 9476657Snate@binkert.org addToOrderList(op_class); 9486657Snate@binkert.org } else if (readyInsts[op_class].top()->seqNum < 9496657Snate@binkert.org (*readyIt[op_class]).oldestInst) { 9506657Snate@binkert.org listOrder.erase(readyIt[op_class]); 9517002Snate@binkert.org addToOrderList(op_class); 9526657Snate@binkert.org } 9536657Snate@binkert.org 9546657Snate@binkert.org DPRINTF(IQ, "Instruction is ready to issue, putting it onto " 9556657Snate@binkert.org "the ready list, PC %#x opclass:%i [sn:%lli].\n", 9566657Snate@binkert.org ready_inst->readPC(), op_class, ready_inst->seqNum); 9576657Snate@binkert.org} 9586657Snate@binkert.org 9596657Snate@binkert.orgtemplate <class Impl> 9606657Snate@binkert.orgvoid 9617007Snate@binkert.orgInstructionQueue<Impl>::rescheduleMemInst(DynInstPtr &resched_inst) 9626657Snate@binkert.org{ 9636657Snate@binkert.org memDepUnit[resched_inst->threadNumber].reschedule(resched_inst); 9646657Snate@binkert.org} 9656657Snate@binkert.org 9666999Snate@binkert.orgtemplate <class Impl> 9676657Snate@binkert.orgvoid 9686657Snate@binkert.orgInstructionQueue<Impl>::replayMemInst(DynInstPtr &replay_inst) 9696657Snate@binkert.org{ 9706657Snate@binkert.org memDepUnit[replay_inst->threadNumber].replay(replay_inst); 9716657Snate@binkert.org} 9726657Snate@binkert.org 9736657Snate@binkert.orgtemplate <class Impl> 9746657Snate@binkert.orgvoid 9756657Snate@binkert.orgInstructionQueue<Impl>::completeMemInst(DynInstPtr &completed_inst) 9766657Snate@binkert.org{ 9776657Snate@binkert.org int tid = completed_inst->threadNumber; 9786657Snate@binkert.org 9796657Snate@binkert.org DPRINTF(IQ, "Completing mem instruction PC:%#x [sn:%lli]\n", 9806657Snate@binkert.org completed_inst->readPC(), completed_inst->seqNum); 9816657Snate@binkert.org 9826657Snate@binkert.org ++freeEntries; 9836657Snate@binkert.org 9846657Snate@binkert.org completed_inst->memOpDone = true; 9856657Snate@binkert.org 9866657Snate@binkert.org memDepUnit[tid].completed(completed_inst); 9877007Snate@binkert.org 9887007Snate@binkert.org count[tid]--; 9897007Snate@binkert.org} 9906657Snate@binkert.org 9916657Snate@binkert.orgtemplate <class Impl> 9926657Snate@binkert.orgvoid 9937007Snate@binkert.orgInstructionQueue<Impl>::violation(DynInstPtr &store, 9947007Snate@binkert.org DynInstPtr &faulting_load) 9957007Snate@binkert.org{ 9966657Snate@binkert.org memDepUnit[store->threadNumber].violation(store, faulting_load); 9976657Snate@binkert.org} 9986657Snate@binkert.org 9996657Snate@binkert.orgtemplate <class Impl> 10006657Snate@binkert.orgvoid 10016657Snate@binkert.orgInstructionQueue<Impl>::squash(unsigned tid) 10026657Snate@binkert.org{ 10036657Snate@binkert.org DPRINTF(IQ, "[tid:%i]: Starting to squash instructions in " 10046657Snate@binkert.org "the IQ.\n", tid); 10056657Snate@binkert.org 10066657Snate@binkert.org // Read instruction sequence number of last instruction out of the 10077007Snate@binkert.org // time buffer. 10087007Snate@binkert.org squashedSeqNum[tid] = fromCommit->commitInfo[tid].doneSeqNum; 10096657Snate@binkert.org 10106657Snate@binkert.org // Call doSquash if there are insts in the IQ 10116657Snate@binkert.org if (count[tid] > 0) { 10126657Snate@binkert.org doSquash(tid); 10136657Snate@binkert.org } 10147007Snate@binkert.org 10157007Snate@binkert.org // Also tell the memory dependence unit to squash. 10167007Snate@binkert.org memDepUnit[tid].squash(squashedSeqNum[tid], tid); 10176657Snate@binkert.org} 10186657Snate@binkert.org 10196657Snate@binkert.orgtemplate <class Impl> 10207007Snate@binkert.orgvoid 10217007Snate@binkert.orgInstructionQueue<Impl>::doSquash(unsigned tid) 10227007Snate@binkert.org{ 10236657Snate@binkert.org // Start at the tail. 10247002Snate@binkert.org ListIt squash_it = instList[tid].end(); 10257002Snate@binkert.org --squash_it; 10266657Snate@binkert.org 10276657Snate@binkert.org DPRINTF(IQ, "[tid:%i]: Squashing until sequence number %i!\n", 10286657Snate@binkert.org tid, squashedSeqNum[tid]); 10296657Snate@binkert.org 10306657Snate@binkert.org // Squash any instructions younger than the squashed sequence number 10316657Snate@binkert.org // given. 10326657Snate@binkert.org while (squash_it != instList[tid].end() && 10336657Snate@binkert.org (*squash_it)->seqNum > squashedSeqNum[tid]) { 10346657Snate@binkert.org 10356657Snate@binkert.org DynInstPtr squashed_inst = (*squash_it); 10366657Snate@binkert.org 10376657Snate@binkert.org // Only handle the instruction if it actually is in the IQ and 10387007Snate@binkert.org // hasn't already been squashed in the IQ. 10397007Snate@binkert.org if (squashed_inst->threadNumber != tid || 10406657Snate@binkert.org squashed_inst->isSquashedInIQ()) { 10416657Snate@binkert.org --squash_it; 10426657Snate@binkert.org continue; 10436657Snate@binkert.org } 10446657Snate@binkert.org 10456657Snate@binkert.org if (!squashed_inst->isIssued() || 10466657Snate@binkert.org (squashed_inst->isMemRef() && 10476657Snate@binkert.org !squashed_inst->memOpDone)) { 10486657Snate@binkert.org 10496657Snate@binkert.org // Remove the instruction from the dependency list. 10506657Snate@binkert.org if (!squashed_inst->isNonSpeculative() && 10516657Snate@binkert.org !squashed_inst->isStoreConditional() && 10526657Snate@binkert.org !squashed_inst->isMemBarrier() && 10536657Snate@binkert.org !squashed_inst->isWriteBarrier()) { 10546657Snate@binkert.org 10557007Snate@binkert.org for (int src_reg_idx = 0; 10566999Snate@binkert.org src_reg_idx < squashed_inst->numSrcRegs(); 10577007Snate@binkert.org src_reg_idx++) 10587007Snate@binkert.org { 10597007Snate@binkert.org PhysRegIndex src_reg = 10607007Snate@binkert.org squashed_inst->renamedSrcRegIdx(src_reg_idx); 10617007Snate@binkert.org 10627007Snate@binkert.org // Only remove it from the dependency graph if it 10636657Snate@binkert.org // was placed there in the first place. 10646657Snate@binkert.org 10656657Snate@binkert.org // Instead of doing a linked list traversal, we 10666657Snate@binkert.org // can just remove these squashed instructions 10676657Snate@binkert.org // either at issue time, or when the register is 10686657Snate@binkert.org // overwritten. The only downside to this is it 10696657Snate@binkert.org // leaves more room for error. 10706657Snate@binkert.org 10716657Snate@binkert.org if (!squashed_inst->isReadySrcRegIdx(src_reg_idx) && 10726657Snate@binkert.org src_reg < numPhysRegs) { 10736657Snate@binkert.org dependGraph.remove(src_reg, squashed_inst); 10746657Snate@binkert.org } 10756657Snate@binkert.org 10766657Snate@binkert.org 10776657Snate@binkert.org ++iqSquashedOperandsExamined; 10786657Snate@binkert.org } 10796657Snate@binkert.org } else { 10806657Snate@binkert.org NonSpecMapIt ns_inst_it = 10816657Snate@binkert.org nonSpecInsts.find(squashed_inst->seqNum); 10826657Snate@binkert.org assert(ns_inst_it != nonSpecInsts.end()); 10836657Snate@binkert.org 10846657Snate@binkert.org (*ns_inst_it).second = NULL; 10856657Snate@binkert.org 10866657Snate@binkert.org nonSpecInsts.erase(ns_inst_it); 10876657Snate@binkert.org 10886657Snate@binkert.org ++iqSquashedNonSpecRemoved; 10896657Snate@binkert.org } 10906657Snate@binkert.org 10916657Snate@binkert.org // Might want to also clear out the head of the dependency graph. 10926999Snate@binkert.org 10936657Snate@binkert.org // Mark it as squashed within the IQ. 10946657Snate@binkert.org squashed_inst->setSquashedInIQ(); 10957007Snate@binkert.org 10967007Snate@binkert.org // @todo: Remove this hack where several statuses are set so the 10976657Snate@binkert.org // inst will flow through the rest of the pipeline. 10986657Snate@binkert.org squashed_inst->setIssued(); 10996657Snate@binkert.org squashed_inst->setCanCommit(); 11006657Snate@binkert.org squashed_inst->removeInIQ(); 11016657Snate@binkert.org 11026657Snate@binkert.org //Update Thread IQ Count 11036657Snate@binkert.org count[squashed_inst->threadNumber]--; 11046657Snate@binkert.org 11056657Snate@binkert.org ++freeEntries; 11066657Snate@binkert.org 11076657Snate@binkert.org DPRINTF(IQ, "[tid:%i]: Instruction [sn:%lli] PC %#x " 11086657Snate@binkert.org "squashed.\n", 11096657Snate@binkert.org tid, squashed_inst->seqNum, squashed_inst->readPC()); 11106657Snate@binkert.org } 11116657Snate@binkert.org 11126657Snate@binkert.org instList[tid].erase(squash_it--); 11136657Snate@binkert.org ++iqSquashedInstsExamined; 11146657Snate@binkert.org } 11156657Snate@binkert.org} 11166657Snate@binkert.org 11176657Snate@binkert.orgtemplate <class Impl> 11186657Snate@binkert.orgbool 11196657Snate@binkert.orgInstructionQueue<Impl>::addToDependents(DynInstPtr &new_inst) 11206657Snate@binkert.org{ 11216657Snate@binkert.org // Loop through the instruction's source registers, adding 11226657Snate@binkert.org // them to the dependency list if they are not ready. 11236657Snate@binkert.org int8_t total_src_regs = new_inst->numSrcRegs(); 11246657Snate@binkert.org bool return_val = false; 11256657Snate@binkert.org 11266657Snate@binkert.org for (int src_reg_idx = 0; 11276657Snate@binkert.org src_reg_idx < total_src_regs; 11286657Snate@binkert.org src_reg_idx++) 11296657Snate@binkert.org { 11306657Snate@binkert.org // Only add it to the dependency graph if it's not ready. 11316657Snate@binkert.org if (!new_inst->isReadySrcRegIdx(src_reg_idx)) { 11326657Snate@binkert.org PhysRegIndex src_reg = new_inst->renamedSrcRegIdx(src_reg_idx); 11336657Snate@binkert.org 11346657Snate@binkert.org // Check the IQ's scoreboard to make sure the register 11356657Snate@binkert.org // hasn't become ready while the instruction was in flight 11366657Snate@binkert.org // between stages. Only if it really isn't ready should 11376657Snate@binkert.org // it be added to the dependency graph. 11386657Snate@binkert.org if (src_reg >= numPhysRegs) { 11396657Snate@binkert.org continue; 11406657Snate@binkert.org } else if (regScoreboard[src_reg] == false) { 11416657Snate@binkert.org DPRINTF(IQ, "Instruction PC %#x has src reg %i that " 11426657Snate@binkert.org "is being added to the dependency chain.\n", 11436657Snate@binkert.org new_inst->readPC(), src_reg); 11446657Snate@binkert.org 11456657Snate@binkert.org dependGraph.insert(src_reg, new_inst); 11466657Snate@binkert.org 11476657Snate@binkert.org // Change the return value to indicate that something 11486657Snate@binkert.org // was added to the dependency graph. 11496657Snate@binkert.org return_val = true; 11506657Snate@binkert.org } else { 11516657Snate@binkert.org DPRINTF(IQ, "Instruction PC %#x has src reg %i that " 11526657Snate@binkert.org "became ready before it reached the IQ.\n", 11536657Snate@binkert.org new_inst->readPC(), src_reg); 11546657Snate@binkert.org // Mark a register ready within the instruction. 11556657Snate@binkert.org new_inst->markSrcRegReady(src_reg_idx); 11566657Snate@binkert.org } 11576657Snate@binkert.org } 11586657Snate@binkert.org } 11596657Snate@binkert.org 11606657Snate@binkert.org return return_val; 11616657Snate@binkert.org} 11626657Snate@binkert.org 11636657Snate@binkert.orgtemplate <class Impl> 11646657Snate@binkert.orgvoid 11656657Snate@binkert.orgInstructionQueue<Impl>::addToProducers(DynInstPtr &new_inst) 11666657Snate@binkert.org{ 11676657Snate@binkert.org // Nothing really needs to be marked when an instruction becomes 11686657Snate@binkert.org // the producer of a register's value, but for convenience a ptr 11696657Snate@binkert.org // to the producing instruction will be placed in the head node of 11706657Snate@binkert.org // the dependency links. 11716657Snate@binkert.org int8_t total_dest_regs = new_inst->numDestRegs(); 11726657Snate@binkert.org 11736657Snate@binkert.org for (int dest_reg_idx = 0; 11746657Snate@binkert.org dest_reg_idx < total_dest_regs; 11756657Snate@binkert.org dest_reg_idx++) 11766657Snate@binkert.org { 11776657Snate@binkert.org PhysRegIndex dest_reg = new_inst->renamedDestRegIdx(dest_reg_idx); 11786657Snate@binkert.org 11796657Snate@binkert.org // Instructions that use the misc regs will have a reg number 11806657Snate@binkert.org // higher than the normal physical registers. In this case these 11816657Snate@binkert.org // registers are not renamed, and there is no need to track 11826657Snate@binkert.org // dependencies as these instructions must be executed at commit. 11836657Snate@binkert.org if (dest_reg >= numPhysRegs) { 11846657Snate@binkert.org continue; 11857007Snate@binkert.org } 11866657Snate@binkert.org 11876657Snate@binkert.org if (!dependGraph.empty(dest_reg)) { 11886657Snate@binkert.org dependGraph.dump(); 11896657Snate@binkert.org panic("Dependency graph %i not empty!", dest_reg); 11906657Snate@binkert.org } 11916657Snate@binkert.org 11926657Snate@binkert.org dependGraph.setInst(dest_reg, new_inst); 11937007Snate@binkert.org 11946657Snate@binkert.org // Mark the scoreboard to say it's not yet ready. 11956657Snate@binkert.org regScoreboard[dest_reg] = false; 11966657Snate@binkert.org } 11976657Snate@binkert.org} 11986657Snate@binkert.org 11996657Snate@binkert.orgtemplate <class Impl> 12006657Snate@binkert.orgvoid 12016657Snate@binkert.orgInstructionQueue<Impl>::addIfReady(DynInstPtr &inst) 12026657Snate@binkert.org{ 12036657Snate@binkert.org // If the instruction now has all of its source registers 12046657Snate@binkert.org // available, then add it to the list of ready instructions. 12056657Snate@binkert.org if (inst->readyToIssue()) { 12066657Snate@binkert.org 12076657Snate@binkert.org //Add the instruction to the proper ready list. 12086657Snate@binkert.org if (inst->isMemRef()) { 12097007Snate@binkert.org 12106657Snate@binkert.org DPRINTF(IQ, "Checking if memory instruction can issue.\n"); 12116657Snate@binkert.org 12126657Snate@binkert.org // Message to the mem dependence unit that this instruction has 12136657Snate@binkert.org // its registers ready. 12146657Snate@binkert.org memDepUnit[inst->threadNumber].regsReady(inst); 12156657Snate@binkert.org 12166657Snate@binkert.org return; 12176657Snate@binkert.org } 12186657Snate@binkert.org 12196657Snate@binkert.org OpClass op_class = inst->opClass(); 12206657Snate@binkert.org 12216657Snate@binkert.org DPRINTF(IQ, "Instruction is ready to issue, putting it onto " 12226657Snate@binkert.org "the ready list, PC %#x opclass:%i [sn:%lli].\n", 12236657Snate@binkert.org inst->readPC(), op_class, inst->seqNum); 12246657Snate@binkert.org 12256657Snate@binkert.org readyInsts[op_class].push(inst); 12266657Snate@binkert.org 12276657Snate@binkert.org // Will need to reorder the list if either a queue is not on the list, 12286657Snate@binkert.org // or it has an older instruction than last time. 12296657Snate@binkert.org if (!queueOnList[op_class]) { 12306657Snate@binkert.org addToOrderList(op_class); 12316657Snate@binkert.org } else if (readyInsts[op_class].top()->seqNum < 1232 (*readyIt[op_class]).oldestInst) { 1233 listOrder.erase(readyIt[op_class]); 1234 addToOrderList(op_class); 1235 } 1236 } 1237} 1238 1239template <class Impl> 1240int 1241InstructionQueue<Impl>::countInsts() 1242{ 1243#if 0 1244 //ksewell:This works but definitely could use a cleaner write 1245 //with a more intuitive way of counting. Right now it's 1246 //just brute force .... 1247 // Change the #if if you want to use this method. 1248 int total_insts = 0; 1249 1250 for (int i = 0; i < numThreads; ++i) { 1251 ListIt count_it = instList[i].begin(); 1252 1253 while (count_it != instList[i].end()) { 1254 if (!(*count_it)->isSquashed() && !(*count_it)->isSquashedInIQ()) { 1255 if (!(*count_it)->isIssued()) { 1256 ++total_insts; 1257 } else if ((*count_it)->isMemRef() && 1258 !(*count_it)->memOpDone) { 1259 // Loads that have not been marked as executed still count 1260 // towards the total instructions. 1261 ++total_insts; 1262 } 1263 } 1264 1265 ++count_it; 1266 } 1267 } 1268 1269 return total_insts; 1270#else 1271 return numEntries - freeEntries; 1272#endif 1273} 1274 1275template <class Impl> 1276void 1277InstructionQueue<Impl>::dumpLists() 1278{ 1279 for (int i = 0; i < Num_OpClasses; ++i) { 1280 cprintf("Ready list %i size: %i\n", i, readyInsts[i].size()); 1281 1282 cprintf("\n"); 1283 } 1284 1285 cprintf("Non speculative list size: %i\n", nonSpecInsts.size()); 1286 1287 NonSpecMapIt non_spec_it = nonSpecInsts.begin(); 1288 NonSpecMapIt non_spec_end_it = nonSpecInsts.end(); 1289 1290 cprintf("Non speculative list: "); 1291 1292 while (non_spec_it != non_spec_end_it) { 1293 cprintf("%#x [sn:%lli]", (*non_spec_it).second->readPC(), 1294 (*non_spec_it).second->seqNum); 1295 ++non_spec_it; 1296 } 1297 1298 cprintf("\n"); 1299 1300 ListOrderIt list_order_it = listOrder.begin(); 1301 ListOrderIt list_order_end_it = listOrder.end(); 1302 int i = 1; 1303 1304 cprintf("List order: "); 1305 1306 while (list_order_it != list_order_end_it) { 1307 cprintf("%i OpClass:%i [sn:%lli] ", i, (*list_order_it).queueType, 1308 (*list_order_it).oldestInst); 1309 1310 ++list_order_it; 1311 ++i; 1312 } 1313 1314 cprintf("\n"); 1315} 1316 1317 1318template <class Impl> 1319void 1320InstructionQueue<Impl>::dumpInsts() 1321{ 1322 for (int i = 0; i < numThreads; ++i) { 1323 int num = 0; 1324 int valid_num = 0; 1325 ListIt inst_list_it = instList[i].begin(); 1326 1327 while (inst_list_it != instList[i].end()) 1328 { 1329 cprintf("Instruction:%i\n", 1330 num); 1331 if (!(*inst_list_it)->isSquashed()) { 1332 if (!(*inst_list_it)->isIssued()) { 1333 ++valid_num; 1334 cprintf("Count:%i\n", valid_num); 1335 } else if ((*inst_list_it)->isMemRef() && 1336 !(*inst_list_it)->memOpDone) { 1337 // Loads that have not been marked as executed 1338 // still count towards the total instructions. 1339 ++valid_num; 1340 cprintf("Count:%i\n", valid_num); 1341 } 1342 } 1343 1344 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 1345 "Issued:%i\nSquashed:%i\n", 1346 (*inst_list_it)->readPC(), 1347 (*inst_list_it)->seqNum, 1348 (*inst_list_it)->threadNumber, 1349 (*inst_list_it)->isIssued(), 1350 (*inst_list_it)->isSquashed()); 1351 1352 if ((*inst_list_it)->isMemRef()) { 1353 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); 1354 } 1355 1356 cprintf("\n"); 1357 1358 inst_list_it++; 1359 ++num; 1360 } 1361 } 1362 1363 cprintf("Insts to Execute list:\n"); 1364 1365 int num = 0; 1366 int valid_num = 0; 1367 ListIt inst_list_it = instsToExecute.begin(); 1368 1369 while (inst_list_it != instsToExecute.end()) 1370 { 1371 cprintf("Instruction:%i\n", 1372 num); 1373 if (!(*inst_list_it)->isSquashed()) { 1374 if (!(*inst_list_it)->isIssued()) { 1375 ++valid_num; 1376 cprintf("Count:%i\n", valid_num); 1377 } else if ((*inst_list_it)->isMemRef() && 1378 !(*inst_list_it)->memOpDone) { 1379 // Loads that have not been marked as executed 1380 // still count towards the total instructions. 1381 ++valid_num; 1382 cprintf("Count:%i\n", valid_num); 1383 } 1384 } 1385 1386 cprintf("PC:%#x\n[sn:%lli]\n[tid:%i]\n" 1387 "Issued:%i\nSquashed:%i\n", 1388 (*inst_list_it)->readPC(), 1389 (*inst_list_it)->seqNum, 1390 (*inst_list_it)->threadNumber, 1391 (*inst_list_it)->isIssued(), 1392 (*inst_list_it)->isSquashed()); 1393 1394 if ((*inst_list_it)->isMemRef()) { 1395 cprintf("MemOpDone:%i\n", (*inst_list_it)->memOpDone); 1396 } 1397 1398 cprintf("\n"); 1399 1400 inst_list_it++; 1401 ++num; 1402 } 1403} 1404