iew_impl.hh revision 8471
15132Sgblack@eecs.umich.edu/* 25132Sgblack@eecs.umich.edu * Copyright (c) 2010 ARM Limited 35132Sgblack@eecs.umich.edu * All rights reserved. 45132Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 135132Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Copyright (c) 2004-2006 The Regents of The University of Michigan 157087Snate@binkert.org * All rights reserved. 167087Snate@binkert.org * 177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 187087Snate@binkert.org * modification, are permitted provided that the following conditions are 197087Snate@binkert.org * met: redistributions of source code must retain the above copyright 207087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 225132Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237087Snate@binkert.org * documentation and/or other materials provided with the distribution; 245132Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 255132Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 265132Sgblack@eecs.umich.edu * this software without specific prior written permission. 275132Sgblack@eecs.umich.edu * 285132Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 295132Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 305132Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 315132Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 325132Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 335132Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 345132Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 355132Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365132Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375132Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385132Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395132Sgblack@eecs.umich.edu * 405612Sgblack@eecs.umich.edu * Authors: Kevin Lim 415625Sgblack@eecs.umich.edu */ 427629Sgblack@eecs.umich.edu 435132Sgblack@eecs.umich.edu// @todo: Fix the instantaneous communication among all the stages within 445132Sgblack@eecs.umich.edu// iew. There's a clear delay between issue and execute, yet backwards 455625Sgblack@eecs.umich.edu// communication happens simultaneously. 465132Sgblack@eecs.umich.edu 475132Sgblack@eecs.umich.edu#include <queue> 485132Sgblack@eecs.umich.edu 495299Sgblack@eecs.umich.edu#include "arch/utility.hh" 505132Sgblack@eecs.umich.edu#include "config/the_isa.hh" 515132Sgblack@eecs.umich.edu#include "cpu/o3/fu_pool.hh" 525132Sgblack@eecs.umich.edu#include "cpu/o3/iew.hh" 535132Sgblack@eecs.umich.edu#include "cpu/timebuf.hh" 545132Sgblack@eecs.umich.edu#include "debug/Activity.hh" 555299Sgblack@eecs.umich.edu#include "debug/Decode.hh" 565299Sgblack@eecs.umich.edu#include "debug/IEW.hh" 575132Sgblack@eecs.umich.edu#include "params/DerivO3CPU.hh" 585625Sgblack@eecs.umich.edu 595625Sgblack@eecs.umich.eduusing namespace std; 605625Sgblack@eecs.umich.edu 615627Sgblack@eecs.umich.edutemplate<class Impl> 625627Sgblack@eecs.umich.eduDefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) 637704Sgblack@eecs.umich.edu : issueToExecQueue(params->backComSize, params->forwardComSize), 647704Sgblack@eecs.umich.edu cpu(_cpu), 657704Sgblack@eecs.umich.edu instQueue(_cpu, this, params), 667704Sgblack@eecs.umich.edu ldstQueue(_cpu, this, params), 675132Sgblack@eecs.umich.edu fuPool(params->fuPool), 686220Sgblack@eecs.umich.edu commitToIEWDelay(params->commitToIEWDelay), 696220Sgblack@eecs.umich.edu renameToIEWDelay(params->renameToIEWDelay), 706220Sgblack@eecs.umich.edu issueToExecuteDelay(params->issueToExecuteDelay), 716220Sgblack@eecs.umich.edu dispatchWidth(params->dispatchWidth), 726220Sgblack@eecs.umich.edu issueWidth(params->issueWidth), 736220Sgblack@eecs.umich.edu wbOutstanding(0), 746220Sgblack@eecs.umich.edu wbWidth(params->wbWidth), 756220Sgblack@eecs.umich.edu numThreads(params->numThreads), 766220Sgblack@eecs.umich.edu switchedOut(false) 776220Sgblack@eecs.umich.edu{ 786220Sgblack@eecs.umich.edu _status = Active; 796220Sgblack@eecs.umich.edu exeStatus = Running; 806222Sgblack@eecs.umich.edu wbStatus = Idle; 816222Sgblack@eecs.umich.edu 826222Sgblack@eecs.umich.edu // Setup wire to read instructions coming from issue. 836222Sgblack@eecs.umich.edu fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 846222Sgblack@eecs.umich.edu 856222Sgblack@eecs.umich.edu // Instruction queue needs the queue between issue and execute. 866222Sgblack@eecs.umich.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 876222Sgblack@eecs.umich.edu 886222Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 896222Sgblack@eecs.umich.edu dispatchStatus[tid] = Running; 906220Sgblack@eecs.umich.edu stalls[tid].commit = false; 916220Sgblack@eecs.umich.edu fetchRedirect[tid] = false; 926220Sgblack@eecs.umich.edu } 936222Sgblack@eecs.umich.edu 946220Sgblack@eecs.umich.edu wbMax = wbWidth * params->wbDepth; 956222Sgblack@eecs.umich.edu 966220Sgblack@eecs.umich.edu updateLSQNextCycle = false; 976220Sgblack@eecs.umich.edu 986222Sgblack@eecs.umich.edu ableToIssue = true; 996220Sgblack@eecs.umich.edu 1006220Sgblack@eecs.umich.edu skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 1016220Sgblack@eecs.umich.edu} 1026220Sgblack@eecs.umich.edu 1036222Sgblack@eecs.umich.edutemplate <class Impl> 1046220Sgblack@eecs.umich.edustd::string 1056220Sgblack@eecs.umich.eduDefaultIEW<Impl>::name() const 1066220Sgblack@eecs.umich.edu{ 1076220Sgblack@eecs.umich.edu return cpu->name() + ".iew"; 1086220Sgblack@eecs.umich.edu} 1096220Sgblack@eecs.umich.edu 1106220Sgblack@eecs.umich.edutemplate <class Impl> 1116220Sgblack@eecs.umich.eduvoid 1126220Sgblack@eecs.umich.eduDefaultIEW<Impl>::regStats() 1136220Sgblack@eecs.umich.edu{ 1145299Sgblack@eecs.umich.edu using namespace Stats; 1157532Ssteve.reinhardt@amd.com 1165299Sgblack@eecs.umich.edu instQueue.regStats(); 1177532Ssteve.reinhardt@amd.com ldstQueue.regStats(); 1187532Ssteve.reinhardt@amd.com 1196220Sgblack@eecs.umich.edu iewIdleCycles 1205299Sgblack@eecs.umich.edu .name(name() + ".iewIdleCycles") 1215299Sgblack@eecs.umich.edu .desc("Number of cycles IEW is idle"); 1225299Sgblack@eecs.umich.edu 1235299Sgblack@eecs.umich.edu iewSquashCycles 1245299Sgblack@eecs.umich.edu .name(name() + ".iewSquashCycles") 1255299Sgblack@eecs.umich.edu .desc("Number of cycles IEW is squashing"); 1265299Sgblack@eecs.umich.edu 1275299Sgblack@eecs.umich.edu iewBlockCycles 1285299Sgblack@eecs.umich.edu .name(name() + ".iewBlockCycles") 1295299Sgblack@eecs.umich.edu .desc("Number of cycles IEW is blocking"); 1305299Sgblack@eecs.umich.edu 1315299Sgblack@eecs.umich.edu iewUnblockCycles 1325299Sgblack@eecs.umich.edu .name(name() + ".iewUnblockCycles") 1335299Sgblack@eecs.umich.edu .desc("Number of cycles IEW is unblocking"); 1345299Sgblack@eecs.umich.edu 1355299Sgblack@eecs.umich.edu iewDispatchedInsts 1365299Sgblack@eecs.umich.edu .name(name() + ".iewDispatchedInsts") 1375299Sgblack@eecs.umich.edu .desc("Number of instructions dispatched to IQ"); 1385299Sgblack@eecs.umich.edu 1395299Sgblack@eecs.umich.edu iewDispSquashedInsts 1405299Sgblack@eecs.umich.edu .name(name() + ".iewDispSquashedInsts") 1416220Sgblack@eecs.umich.edu .desc("Number of squashed instructions skipped by dispatch"); 1425299Sgblack@eecs.umich.edu 1435299Sgblack@eecs.umich.edu iewDispLoadInsts 1445299Sgblack@eecs.umich.edu .name(name() + ".iewDispLoadInsts") 1455299Sgblack@eecs.umich.edu .desc("Number of dispatched load instructions"); 1466220Sgblack@eecs.umich.edu 1475299Sgblack@eecs.umich.edu iewDispStoreInsts 1485299Sgblack@eecs.umich.edu .name(name() + ".iewDispStoreInsts") 1496220Sgblack@eecs.umich.edu .desc("Number of dispatched store instructions"); 1506220Sgblack@eecs.umich.edu 1516220Sgblack@eecs.umich.edu iewDispNonSpecInsts 1525299Sgblack@eecs.umich.edu .name(name() + ".iewDispNonSpecInsts") 1535299Sgblack@eecs.umich.edu .desc("Number of dispatched non-speculative instructions"); 1545299Sgblack@eecs.umich.edu 1556220Sgblack@eecs.umich.edu iewIQFullEvents 1565299Sgblack@eecs.umich.edu .name(name() + ".iewIQFullEvents") 1576220Sgblack@eecs.umich.edu .desc("Number of times the IQ has become full, causing a stall"); 1585299Sgblack@eecs.umich.edu 1595299Sgblack@eecs.umich.edu iewLSQFullEvents 1605299Sgblack@eecs.umich.edu .name(name() + ".iewLSQFullEvents") 1615299Sgblack@eecs.umich.edu .desc("Number of times the LSQ has become full, causing a stall"); 1626220Sgblack@eecs.umich.edu 1636220Sgblack@eecs.umich.edu memOrderViolationEvents 1646220Sgblack@eecs.umich.edu .name(name() + ".memOrderViolationEvents") 1656220Sgblack@eecs.umich.edu .desc("Number of memory order violations"); 1665299Sgblack@eecs.umich.edu 1675299Sgblack@eecs.umich.edu predictedTakenIncorrect 1685299Sgblack@eecs.umich.edu .name(name() + ".predictedTakenIncorrect") 1695299Sgblack@eecs.umich.edu .desc("Number of branches that were predicted taken incorrectly"); 1705299Sgblack@eecs.umich.edu 1716220Sgblack@eecs.umich.edu predictedNotTakenIncorrect 1726220Sgblack@eecs.umich.edu .name(name() + ".predictedNotTakenIncorrect") 1735299Sgblack@eecs.umich.edu .desc("Number of branches that were predicted not taken incorrectly"); 1746220Sgblack@eecs.umich.edu 1756220Sgblack@eecs.umich.edu branchMispredicts 1766220Sgblack@eecs.umich.edu .name(name() + ".branchMispredicts") 1776220Sgblack@eecs.umich.edu .desc("Number of branch mispredicts detected at execute"); 1786220Sgblack@eecs.umich.edu 1796220Sgblack@eecs.umich.edu branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 1806220Sgblack@eecs.umich.edu 1816220Sgblack@eecs.umich.edu iewExecutedInsts 1826220Sgblack@eecs.umich.edu .name(name() + ".iewExecutedInsts") 1836220Sgblack@eecs.umich.edu .desc("Number of executed instructions"); 1846220Sgblack@eecs.umich.edu 1856220Sgblack@eecs.umich.edu iewExecLoadInsts 1866220Sgblack@eecs.umich.edu .init(cpu->numThreads) 1876220Sgblack@eecs.umich.edu .name(name() + ".iewExecLoadInsts") 1886220Sgblack@eecs.umich.edu .desc("Number of load instructions executed") 1896220Sgblack@eecs.umich.edu .flags(total); 1906220Sgblack@eecs.umich.edu 1916220Sgblack@eecs.umich.edu iewExecSquashedInsts 1926220Sgblack@eecs.umich.edu .name(name() + ".iewExecSquashedInsts") 1936220Sgblack@eecs.umich.edu .desc("Number of squashed instructions skipped in execute"); 1946220Sgblack@eecs.umich.edu 1956220Sgblack@eecs.umich.edu iewExecutedSwp 1966220Sgblack@eecs.umich.edu .init(cpu->numThreads) 1976220Sgblack@eecs.umich.edu .name(name() + ".exec_swp") 1986220Sgblack@eecs.umich.edu .desc("number of swp insts executed") 1996712Snate@binkert.org .flags(total); 2006220Sgblack@eecs.umich.edu 2016220Sgblack@eecs.umich.edu iewExecutedNop 2026220Sgblack@eecs.umich.edu .init(cpu->numThreads) 2036220Sgblack@eecs.umich.edu .name(name() + ".exec_nop") 2046220Sgblack@eecs.umich.edu .desc("number of nop insts executed") 2056220Sgblack@eecs.umich.edu .flags(total); 2066220Sgblack@eecs.umich.edu 2076220Sgblack@eecs.umich.edu iewExecutedRefs 2086220Sgblack@eecs.umich.edu .init(cpu->numThreads) 2096220Sgblack@eecs.umich.edu .name(name() + ".exec_refs") 2106220Sgblack@eecs.umich.edu .desc("number of memory reference insts executed") 2116220Sgblack@eecs.umich.edu .flags(total); 2126220Sgblack@eecs.umich.edu 2136220Sgblack@eecs.umich.edu iewExecutedBranches 2146220Sgblack@eecs.umich.edu .init(cpu->numThreads) 2156220Sgblack@eecs.umich.edu .name(name() + ".exec_branches") 2166220Sgblack@eecs.umich.edu .desc("Number of branches executed") 2176220Sgblack@eecs.umich.edu .flags(total); 2186220Sgblack@eecs.umich.edu 2196220Sgblack@eecs.umich.edu iewExecStoreInsts 2206220Sgblack@eecs.umich.edu .name(name() + ".exec_stores") 2216220Sgblack@eecs.umich.edu .desc("Number of stores executed") 2226220Sgblack@eecs.umich.edu .flags(total); 2236220Sgblack@eecs.umich.edu iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts; 2246220Sgblack@eecs.umich.edu 2256220Sgblack@eecs.umich.edu iewExecRate 2266220Sgblack@eecs.umich.edu .name(name() + ".exec_rate") 2276220Sgblack@eecs.umich.edu .desc("Inst execution rate") 2286220Sgblack@eecs.umich.edu .flags(total); 2296220Sgblack@eecs.umich.edu 2306220Sgblack@eecs.umich.edu iewExecRate = iewExecutedInsts / cpu->numCycles; 2316220Sgblack@eecs.umich.edu 2325299Sgblack@eecs.umich.edu iewInstsToCommit 2335299Sgblack@eecs.umich.edu .init(cpu->numThreads) 2345299Sgblack@eecs.umich.edu .name(name() + ".wb_sent") 2355299Sgblack@eecs.umich.edu .desc("cumulative count of insts sent to commit") 2365299Sgblack@eecs.umich.edu .flags(total); 2375299Sgblack@eecs.umich.edu 2385299Sgblack@eecs.umich.edu writebackCount 2395299Sgblack@eecs.umich.edu .init(cpu->numThreads) 2405299Sgblack@eecs.umich.edu .name(name() + ".wb_count") 2415299Sgblack@eecs.umich.edu .desc("cumulative count of insts written-back") 2425299Sgblack@eecs.umich.edu .flags(total); 2435299Sgblack@eecs.umich.edu 2445299Sgblack@eecs.umich.edu producerInst 2455299Sgblack@eecs.umich.edu .init(cpu->numThreads) 2465299Sgblack@eecs.umich.edu .name(name() + ".wb_producers") 2475299Sgblack@eecs.umich.edu .desc("num instructions producing a value") 2485299Sgblack@eecs.umich.edu .flags(total); 2495299Sgblack@eecs.umich.edu 2505299Sgblack@eecs.umich.edu consumerInst 2515299Sgblack@eecs.umich.edu .init(cpu->numThreads) 2525299Sgblack@eecs.umich.edu .name(name() + ".wb_consumers") 2535299Sgblack@eecs.umich.edu .desc("num instructions consuming a value") 2545299Sgblack@eecs.umich.edu .flags(total); 2555299Sgblack@eecs.umich.edu 2565299Sgblack@eecs.umich.edu wbPenalized 2575299Sgblack@eecs.umich.edu .init(cpu->numThreads) 2585299Sgblack@eecs.umich.edu .name(name() + ".wb_penalized") 2595299Sgblack@eecs.umich.edu .desc("number of instrctions required to write to 'other' IQ") 2605299Sgblack@eecs.umich.edu .flags(total); 2615299Sgblack@eecs.umich.edu 2625299Sgblack@eecs.umich.edu wbPenalizedRate 2635299Sgblack@eecs.umich.edu .name(name() + ".wb_penalized_rate") 2645299Sgblack@eecs.umich.edu .desc ("fraction of instructions written-back that wrote to 'other' IQ") 2655299Sgblack@eecs.umich.edu .flags(total); 2665299Sgblack@eecs.umich.edu 2675299Sgblack@eecs.umich.edu wbPenalizedRate = wbPenalized / writebackCount; 2685299Sgblack@eecs.umich.edu 2695299Sgblack@eecs.umich.edu wbFanout 2705299Sgblack@eecs.umich.edu .name(name() + ".wb_fanout") 2715299Sgblack@eecs.umich.edu .desc("average fanout of values written-back") 2725299Sgblack@eecs.umich.edu .flags(total); 2735299Sgblack@eecs.umich.edu 2745299Sgblack@eecs.umich.edu wbFanout = producerInst / consumerInst; 2755299Sgblack@eecs.umich.edu 2765299Sgblack@eecs.umich.edu wbRate 2775299Sgblack@eecs.umich.edu .name(name() + ".wb_rate") 2785299Sgblack@eecs.umich.edu .desc("insts written-back per cycle") 2795299Sgblack@eecs.umich.edu .flags(total); 2805299Sgblack@eecs.umich.edu wbRate = writebackCount / cpu->numCycles; 2815299Sgblack@eecs.umich.edu} 2825299Sgblack@eecs.umich.edu 2835299Sgblack@eecs.umich.edutemplate<class Impl> 2845299Sgblack@eecs.umich.eduvoid 2855299Sgblack@eecs.umich.eduDefaultIEW<Impl>::initStage() 2865299Sgblack@eecs.umich.edu{ 2875299Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 2885299Sgblack@eecs.umich.edu toRename->iewInfo[tid].usedIQ = true; 2895299Sgblack@eecs.umich.edu toRename->iewInfo[tid].freeIQEntries = 2906220Sgblack@eecs.umich.edu instQueue.numFreeEntries(tid); 2915299Sgblack@eecs.umich.edu 2925299Sgblack@eecs.umich.edu toRename->iewInfo[tid].usedLSQ = true; 2936220Sgblack@eecs.umich.edu toRename->iewInfo[tid].freeLSQEntries = 2945299Sgblack@eecs.umich.edu ldstQueue.numFreeEntries(tid); 2955299Sgblack@eecs.umich.edu } 2966220Sgblack@eecs.umich.edu 2975299Sgblack@eecs.umich.edu cpu->activateStage(O3CPU::IEWIdx); 2986220Sgblack@eecs.umich.edu} 2995299Sgblack@eecs.umich.edu 3005299Sgblack@eecs.umich.edutemplate<class Impl> 3016220Sgblack@eecs.umich.eduvoid 3025299Sgblack@eecs.umich.eduDefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 3035299Sgblack@eecs.umich.edu{ 3046220Sgblack@eecs.umich.edu timeBuffer = tb_ptr; 3055299Sgblack@eecs.umich.edu 3066220Sgblack@eecs.umich.edu // Setup wire to read information from time buffer, from commit. 3075299Sgblack@eecs.umich.edu fromCommit = timeBuffer->getWire(-commitToIEWDelay); 3085299Sgblack@eecs.umich.edu 3096220Sgblack@eecs.umich.edu // Setup wire to write information back to previous stages. 3106220Sgblack@eecs.umich.edu toRename = timeBuffer->getWire(0); 3116220Sgblack@eecs.umich.edu 3126220Sgblack@eecs.umich.edu toFetch = timeBuffer->getWire(0); 3136220Sgblack@eecs.umich.edu 3146220Sgblack@eecs.umich.edu // Instruction queue also needs main time buffer. 3156220Sgblack@eecs.umich.edu instQueue.setTimeBuffer(tb_ptr); 3166220Sgblack@eecs.umich.edu} 3176220Sgblack@eecs.umich.edu 3185299Sgblack@eecs.umich.edutemplate<class Impl> 3195299Sgblack@eecs.umich.eduvoid 3205299Sgblack@eecs.umich.eduDefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 3216220Sgblack@eecs.umich.edu{ 3225299Sgblack@eecs.umich.edu renameQueue = rq_ptr; 3237720Sgblack@eecs.umich.edu 3245299Sgblack@eecs.umich.edu // Setup wire to read information from rename queue. 3255299Sgblack@eecs.umich.edu fromRename = renameQueue->getWire(-renameToIEWDelay); 3265334Sgblack@eecs.umich.edu} 3275615Sgblack@eecs.umich.edu 3285625Sgblack@eecs.umich.edutemplate<class Impl> 3295615Sgblack@eecs.umich.eduvoid 3305334Sgblack@eecs.umich.eduDefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 3315625Sgblack@eecs.umich.edu{ 3325625Sgblack@eecs.umich.edu iewQueue = iq_ptr; 3335625Sgblack@eecs.umich.edu 3345625Sgblack@eecs.umich.edu // Setup wire to write instructions to commit. 3355625Sgblack@eecs.umich.edu toCommit = iewQueue->getWire(0); 3365625Sgblack@eecs.umich.edu} 3375625Sgblack@eecs.umich.edu 3385299Sgblack@eecs.umich.edutemplate<class Impl> 3395299Sgblack@eecs.umich.eduvoid 3405334Sgblack@eecs.umich.eduDefaultIEW<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 3415615Sgblack@eecs.umich.edu{ 3425615Sgblack@eecs.umich.edu activeThreads = at_ptr; 3435334Sgblack@eecs.umich.edu 3445334Sgblack@eecs.umich.edu ldstQueue.setActiveThreads(at_ptr); 3455334Sgblack@eecs.umich.edu instQueue.setActiveThreads(at_ptr); 3465334Sgblack@eecs.umich.edu} 3475334Sgblack@eecs.umich.edu 3485334Sgblack@eecs.umich.edutemplate<class Impl> 3495615Sgblack@eecs.umich.eduvoid 3505615Sgblack@eecs.umich.eduDefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 3515615Sgblack@eecs.umich.edu{ 3525334Sgblack@eecs.umich.edu scoreboard = sb_ptr; 3535615Sgblack@eecs.umich.edu} 3545615Sgblack@eecs.umich.edu 3555615Sgblack@eecs.umich.edutemplate <class Impl> 3565615Sgblack@eecs.umich.edubool 3575615Sgblack@eecs.umich.eduDefaultIEW<Impl>::drain() 3585615Sgblack@eecs.umich.edu{ 3595334Sgblack@eecs.umich.edu // IEW is ready to drain at any time. 3605334Sgblack@eecs.umich.edu cpu->signalDrained(); 3615625Sgblack@eecs.umich.edu return true; 3625625Sgblack@eecs.umich.edu} 3635625Sgblack@eecs.umich.edu 3645625Sgblack@eecs.umich.edutemplate <class Impl> 3655625Sgblack@eecs.umich.eduvoid 3665625Sgblack@eecs.umich.eduDefaultIEW<Impl>::resume() 3675625Sgblack@eecs.umich.edu{ 3685625Sgblack@eecs.umich.edu} 3695625Sgblack@eecs.umich.edu 3705625Sgblack@eecs.umich.edutemplate <class Impl> 3715625Sgblack@eecs.umich.eduvoid 3725625Sgblack@eecs.umich.eduDefaultIEW<Impl>::switchOut() 3735625Sgblack@eecs.umich.edu{ 3745625Sgblack@eecs.umich.edu // Clear any state. 3755625Sgblack@eecs.umich.edu switchedOut = true; 3765625Sgblack@eecs.umich.edu assert(insts[0].empty()); 3775625Sgblack@eecs.umich.edu assert(skidBuffer[0].empty()); 3785625Sgblack@eecs.umich.edu 3795625Sgblack@eecs.umich.edu instQueue.switchOut(); 3805625Sgblack@eecs.umich.edu ldstQueue.switchOut(); 3815625Sgblack@eecs.umich.edu fuPool->switchOut(); 3825625Sgblack@eecs.umich.edu 3835625Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 3845625Sgblack@eecs.umich.edu while (!insts[tid].empty()) 3855625Sgblack@eecs.umich.edu insts[tid].pop(); 3865625Sgblack@eecs.umich.edu while (!skidBuffer[tid].empty()) 3875625Sgblack@eecs.umich.edu skidBuffer[tid].pop(); 3885625Sgblack@eecs.umich.edu } 3895625Sgblack@eecs.umich.edu} 3905334Sgblack@eecs.umich.edu 3915132Sgblack@eecs.umich.edutemplate <class Impl> 3925132Sgblack@eecs.umich.eduvoid 3935334Sgblack@eecs.umich.eduDefaultIEW<Impl>::takeOverFrom() 3945132Sgblack@eecs.umich.edu{ 3955132Sgblack@eecs.umich.edu // Reset all state. 3965132Sgblack@eecs.umich.edu _status = Active; 3975132Sgblack@eecs.umich.edu exeStatus = Running; 3985132Sgblack@eecs.umich.edu wbStatus = Idle; 3995132Sgblack@eecs.umich.edu switchedOut = false; 4005132Sgblack@eecs.umich.edu 4015132Sgblack@eecs.umich.edu instQueue.takeOverFrom(); 4025132Sgblack@eecs.umich.edu ldstQueue.takeOverFrom(); 4035132Sgblack@eecs.umich.edu fuPool->takeOverFrom(); 4045132Sgblack@eecs.umich.edu 4055132Sgblack@eecs.umich.edu initStage(); 4065132Sgblack@eecs.umich.edu cpu->activityThisCycle(); 4075132Sgblack@eecs.umich.edu 4085132Sgblack@eecs.umich.edu for (ThreadID tid = 0; tid < numThreads; tid++) { 4095132Sgblack@eecs.umich.edu dispatchStatus[tid] = Running; 4105132Sgblack@eecs.umich.edu stalls[tid].commit = false; 4115132Sgblack@eecs.umich.edu fetchRedirect[tid] = false; 4125132Sgblack@eecs.umich.edu } 4135132Sgblack@eecs.umich.edu 414 updateLSQNextCycle = false; 415 416 for (int i = 0; i < issueToExecQueue.getSize(); ++i) { 417 issueToExecQueue.advance(); 418 } 419} 420 421template<class Impl> 422void 423DefaultIEW<Impl>::squash(ThreadID tid) 424{ 425 DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); 426 427 // Tell the IQ to start squashing. 428 instQueue.squash(tid); 429 430 // Tell the LDSTQ to start squashing. 431 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 432 updatedQueues = true; 433 434 // Clear the skid buffer in case it has any data in it. 435 DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", 436 tid, fromCommit->commitInfo[tid].doneSeqNum); 437 438 while (!skidBuffer[tid].empty()) { 439 if (skidBuffer[tid].front()->isLoad() || 440 skidBuffer[tid].front()->isStore() ) { 441 toRename->iewInfo[tid].dispatchedToLSQ++; 442 } 443 444 toRename->iewInfo[tid].dispatched++; 445 446 skidBuffer[tid].pop(); 447 } 448 449 emptyRenameInsts(tid); 450} 451 452template<class Impl> 453void 454DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) 455{ 456 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " 457 "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); 458 459 if (toCommit->squash[tid] == false || 460 inst->seqNum < toCommit->squashedSeqNum[tid]) { 461 toCommit->squash[tid] = true; 462 toCommit->squashedSeqNum[tid] = inst->seqNum; 463 toCommit->branchTaken[tid] = inst->pcState().branching(); 464 465 TheISA::PCState pc = inst->pcState(); 466 TheISA::advancePC(pc, inst->staticInst); 467 468 toCommit->pc[tid] = pc; 469 toCommit->mispredictInst[tid] = inst; 470 toCommit->includeSquashInst[tid] = false; 471 472 wroteToTimeBuffer = true; 473 } 474 475} 476 477template<class Impl> 478void 479DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) 480{ 481 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, " 482 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 483 484 if (toCommit->squash[tid] == false || 485 inst->seqNum < toCommit->squashedSeqNum[tid]) { 486 toCommit->squash[tid] = true; 487 toCommit->squashedSeqNum[tid] = inst->seqNum; 488 TheISA::PCState pc; 489 if (inst->isMemRef() && inst->isIndirectCtrl()) { 490 // If an operation is a control operation as well as a memory 491 // reference we need to use the predicted PC, not the PC+N 492 // This instruction will verify misprediction based on predPC 493 pc = inst->readPredTarg(); 494 } else { 495 pc = inst->pcState(); 496 TheISA::advancePC(pc, inst->staticInst); 497 } 498 toCommit->pc[tid] = pc; 499 toCommit->mispredictInst[tid] = NULL; 500 501 toCommit->includeSquashInst[tid] = false; 502 503 wroteToTimeBuffer = true; 504 } 505} 506 507template<class Impl> 508void 509DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) 510{ 511 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 512 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 513 if (toCommit->squash[tid] == false || 514 inst->seqNum < toCommit->squashedSeqNum[tid]) { 515 toCommit->squash[tid] = true; 516 517 toCommit->squashedSeqNum[tid] = inst->seqNum; 518 toCommit->pc[tid] = inst->pcState(); 519 toCommit->mispredictInst[tid] = NULL; 520 521 // Must include the broadcasted SN in the squash. 522 toCommit->includeSquashInst[tid] = true; 523 524 ldstQueue.setLoadBlockedHandled(tid); 525 526 wroteToTimeBuffer = true; 527 } 528} 529 530template<class Impl> 531void 532DefaultIEW<Impl>::block(ThreadID tid) 533{ 534 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 535 536 if (dispatchStatus[tid] != Blocked && 537 dispatchStatus[tid] != Unblocking) { 538 toRename->iewBlock[tid] = true; 539 wroteToTimeBuffer = true; 540 } 541 542 // Add the current inputs to the skid buffer so they can be 543 // reprocessed when this stage unblocks. 544 skidInsert(tid); 545 546 dispatchStatus[tid] = Blocked; 547} 548 549template<class Impl> 550void 551DefaultIEW<Impl>::unblock(ThreadID tid) 552{ 553 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 554 "buffer %u.\n",tid, tid); 555 556 // If the skid bufffer is empty, signal back to previous stages to unblock. 557 // Also switch status to running. 558 if (skidBuffer[tid].empty()) { 559 toRename->iewUnblock[tid] = true; 560 wroteToTimeBuffer = true; 561 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 562 dispatchStatus[tid] = Running; 563 } 564} 565 566template<class Impl> 567void 568DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 569{ 570 instQueue.wakeDependents(inst); 571} 572 573template<class Impl> 574void 575DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 576{ 577 instQueue.rescheduleMemInst(inst); 578} 579 580template<class Impl> 581void 582DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 583{ 584 instQueue.replayMemInst(inst); 585} 586 587template<class Impl> 588void 589DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 590{ 591 // This function should not be called after writebackInsts in a 592 // single cycle. That will cause problems with an instruction 593 // being added to the queue to commit without being processed by 594 // writebackInsts prior to being sent to commit. 595 596 // First check the time slot that this instruction will write 597 // to. If there are free write ports at the time, then go ahead 598 // and write the instruction to that time. If there are not, 599 // keep looking back to see where's the first time there's a 600 // free slot. 601 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 602 ++wbNumInst; 603 if (wbNumInst == wbWidth) { 604 ++wbCycle; 605 wbNumInst = 0; 606 } 607 608 assert((wbCycle * wbWidth + wbNumInst) <= wbMax); 609 } 610 611 DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", 612 wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); 613 // Add finished instruction to queue to commit. 614 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 615 (*iewQueue)[wbCycle].size++; 616} 617 618template <class Impl> 619unsigned 620DefaultIEW<Impl>::validInstsFromRename() 621{ 622 unsigned inst_count = 0; 623 624 for (int i=0; i<fromRename->size; i++) { 625 if (!fromRename->insts[i]->isSquashed()) 626 inst_count++; 627 } 628 629 return inst_count; 630} 631 632template<class Impl> 633void 634DefaultIEW<Impl>::skidInsert(ThreadID tid) 635{ 636 DynInstPtr inst = NULL; 637 638 while (!insts[tid].empty()) { 639 inst = insts[tid].front(); 640 641 insts[tid].pop(); 642 643 DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%s into " 644 "dispatch skidBuffer %i\n",tid, inst->seqNum, 645 inst->pcState(),tid); 646 647 skidBuffer[tid].push(inst); 648 } 649 650 assert(skidBuffer[tid].size() <= skidBufferMax && 651 "Skidbuffer Exceeded Max Size"); 652} 653 654template<class Impl> 655int 656DefaultIEW<Impl>::skidCount() 657{ 658 int max=0; 659 660 list<ThreadID>::iterator threads = activeThreads->begin(); 661 list<ThreadID>::iterator end = activeThreads->end(); 662 663 while (threads != end) { 664 ThreadID tid = *threads++; 665 unsigned thread_count = skidBuffer[tid].size(); 666 if (max < thread_count) 667 max = thread_count; 668 } 669 670 return max; 671} 672 673template<class Impl> 674bool 675DefaultIEW<Impl>::skidsEmpty() 676{ 677 list<ThreadID>::iterator threads = activeThreads->begin(); 678 list<ThreadID>::iterator end = activeThreads->end(); 679 680 while (threads != end) { 681 ThreadID tid = *threads++; 682 683 if (!skidBuffer[tid].empty()) 684 return false; 685 } 686 687 return true; 688} 689 690template <class Impl> 691void 692DefaultIEW<Impl>::updateStatus() 693{ 694 bool any_unblocking = false; 695 696 list<ThreadID>::iterator threads = activeThreads->begin(); 697 list<ThreadID>::iterator end = activeThreads->end(); 698 699 while (threads != end) { 700 ThreadID tid = *threads++; 701 702 if (dispatchStatus[tid] == Unblocking) { 703 any_unblocking = true; 704 break; 705 } 706 } 707 708 // If there are no ready instructions waiting to be scheduled by the IQ, 709 // and there's no stores waiting to write back, and dispatch is not 710 // unblocking, then there is no internal activity for the IEW stage. 711 instQueue.intInstQueueReads++; 712 if (_status == Active && !instQueue.hasReadyInsts() && 713 !ldstQueue.willWB() && !any_unblocking) { 714 DPRINTF(IEW, "IEW switching to idle\n"); 715 716 deactivateStage(); 717 718 _status = Inactive; 719 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 720 ldstQueue.willWB() || 721 any_unblocking)) { 722 // Otherwise there is internal activity. Set to active. 723 DPRINTF(IEW, "IEW switching to active\n"); 724 725 activateStage(); 726 727 _status = Active; 728 } 729} 730 731template <class Impl> 732void 733DefaultIEW<Impl>::resetEntries() 734{ 735 instQueue.resetEntries(); 736 ldstQueue.resetEntries(); 737} 738 739template <class Impl> 740void 741DefaultIEW<Impl>::readStallSignals(ThreadID tid) 742{ 743 if (fromCommit->commitBlock[tid]) { 744 stalls[tid].commit = true; 745 } 746 747 if (fromCommit->commitUnblock[tid]) { 748 assert(stalls[tid].commit); 749 stalls[tid].commit = false; 750 } 751} 752 753template <class Impl> 754bool 755DefaultIEW<Impl>::checkStall(ThreadID tid) 756{ 757 bool ret_val(false); 758 759 if (stalls[tid].commit) { 760 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 761 ret_val = true; 762 } else if (instQueue.isFull(tid)) { 763 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 764 ret_val = true; 765 } else if (ldstQueue.isFull(tid)) { 766 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 767 768 if (ldstQueue.numLoads(tid) > 0 ) { 769 770 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 771 tid,ldstQueue.getLoadHeadSeqNum(tid)); 772 } 773 774 if (ldstQueue.numStores(tid) > 0) { 775 776 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 777 tid,ldstQueue.getStoreHeadSeqNum(tid)); 778 } 779 780 ret_val = true; 781 } else if (ldstQueue.isStalled(tid)) { 782 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 783 ret_val = true; 784 } 785 786 return ret_val; 787} 788 789template <class Impl> 790void 791DefaultIEW<Impl>::checkSignalsAndUpdate(ThreadID tid) 792{ 793 // Check if there's a squash signal, squash if there is 794 // Check stall signals, block if there is. 795 // If status was Blocked 796 // if so then go to unblocking 797 // If status was Squashing 798 // check if squashing is not high. Switch to running this cycle. 799 800 readStallSignals(tid); 801 802 if (fromCommit->commitInfo[tid].squash) { 803 squash(tid); 804 805 if (dispatchStatus[tid] == Blocked || 806 dispatchStatus[tid] == Unblocking) { 807 toRename->iewUnblock[tid] = true; 808 wroteToTimeBuffer = true; 809 } 810 811 dispatchStatus[tid] = Squashing; 812 fetchRedirect[tid] = false; 813 return; 814 } 815 816 if (fromCommit->commitInfo[tid].robSquashing) { 817 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); 818 819 dispatchStatus[tid] = Squashing; 820 emptyRenameInsts(tid); 821 wroteToTimeBuffer = true; 822 return; 823 } 824 825 if (checkStall(tid)) { 826 block(tid); 827 dispatchStatus[tid] = Blocked; 828 return; 829 } 830 831 if (dispatchStatus[tid] == Blocked) { 832 // Status from previous cycle was blocked, but there are no more stall 833 // conditions. Switch over to unblocking. 834 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 835 tid); 836 837 dispatchStatus[tid] = Unblocking; 838 839 unblock(tid); 840 841 return; 842 } 843 844 if (dispatchStatus[tid] == Squashing) { 845 // Switch status to running if rename isn't being told to block or 846 // squash this cycle. 847 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 848 tid); 849 850 dispatchStatus[tid] = Running; 851 852 return; 853 } 854} 855 856template <class Impl> 857void 858DefaultIEW<Impl>::sortInsts() 859{ 860 int insts_from_rename = fromRename->size; 861#ifdef DEBUG 862 for (ThreadID tid = 0; tid < numThreads; tid++) 863 assert(insts[tid].empty()); 864#endif 865 for (int i = 0; i < insts_from_rename; ++i) { 866 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 867 } 868} 869 870template <class Impl> 871void 872DefaultIEW<Impl>::emptyRenameInsts(ThreadID tid) 873{ 874 DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); 875 876 while (!insts[tid].empty()) { 877 878 if (insts[tid].front()->isLoad() || 879 insts[tid].front()->isStore() ) { 880 toRename->iewInfo[tid].dispatchedToLSQ++; 881 } 882 883 toRename->iewInfo[tid].dispatched++; 884 885 insts[tid].pop(); 886 } 887} 888 889template <class Impl> 890void 891DefaultIEW<Impl>::wakeCPU() 892{ 893 cpu->wakeCPU(); 894} 895 896template <class Impl> 897void 898DefaultIEW<Impl>::activityThisCycle() 899{ 900 DPRINTF(Activity, "Activity this cycle.\n"); 901 cpu->activityThisCycle(); 902} 903 904template <class Impl> 905inline void 906DefaultIEW<Impl>::activateStage() 907{ 908 DPRINTF(Activity, "Activating stage.\n"); 909 cpu->activateStage(O3CPU::IEWIdx); 910} 911 912template <class Impl> 913inline void 914DefaultIEW<Impl>::deactivateStage() 915{ 916 DPRINTF(Activity, "Deactivating stage.\n"); 917 cpu->deactivateStage(O3CPU::IEWIdx); 918} 919 920template<class Impl> 921void 922DefaultIEW<Impl>::dispatch(ThreadID tid) 923{ 924 // If status is Running or idle, 925 // call dispatchInsts() 926 // If status is Unblocking, 927 // buffer any instructions coming from rename 928 // continue trying to empty skid buffer 929 // check if stall conditions have passed 930 931 if (dispatchStatus[tid] == Blocked) { 932 ++iewBlockCycles; 933 934 } else if (dispatchStatus[tid] == Squashing) { 935 ++iewSquashCycles; 936 } 937 938 // Dispatch should try to dispatch as many instructions as its bandwidth 939 // will allow, as long as it is not currently blocked. 940 if (dispatchStatus[tid] == Running || 941 dispatchStatus[tid] == Idle) { 942 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 943 "dispatch.\n", tid); 944 945 dispatchInsts(tid); 946 } else if (dispatchStatus[tid] == Unblocking) { 947 // Make sure that the skid buffer has something in it if the 948 // status is unblocking. 949 assert(!skidsEmpty()); 950 951 // If the status was unblocking, then instructions from the skid 952 // buffer were used. Remove those instructions and handle 953 // the rest of unblocking. 954 dispatchInsts(tid); 955 956 ++iewUnblockCycles; 957 958 if (validInstsFromRename()) { 959 // Add the current inputs to the skid buffer so they can be 960 // reprocessed when this stage unblocks. 961 skidInsert(tid); 962 } 963 964 unblock(tid); 965 } 966} 967 968template <class Impl> 969void 970DefaultIEW<Impl>::dispatchInsts(ThreadID tid) 971{ 972 // Obtain instructions from skid buffer if unblocking, or queue from rename 973 // otherwise. 974 std::queue<DynInstPtr> &insts_to_dispatch = 975 dispatchStatus[tid] == Unblocking ? 976 skidBuffer[tid] : insts[tid]; 977 978 int insts_to_add = insts_to_dispatch.size(); 979 980 DynInstPtr inst; 981 bool add_to_iq = false; 982 int dis_num_inst = 0; 983 984 // Loop through the instructions, putting them in the instruction 985 // queue. 986 for ( ; dis_num_inst < insts_to_add && 987 dis_num_inst < dispatchWidth; 988 ++dis_num_inst) 989 { 990 inst = insts_to_dispatch.front(); 991 992 if (dispatchStatus[tid] == Unblocking) { 993 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 994 "buffer\n", tid); 995 } 996 997 // Make sure there's a valid instruction there. 998 assert(inst); 999 1000 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " 1001 "IQ.\n", 1002 tid, inst->pcState(), inst->seqNum, inst->threadNumber); 1003 1004 // Be sure to mark these instructions as ready so that the 1005 // commit stage can go ahead and execute them, and mark 1006 // them as issued so the IQ doesn't reprocess them. 1007 1008 // Check for squashed instructions. 1009 if (inst->isSquashed()) { 1010 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 1011 "not adding to IQ.\n", tid); 1012 1013 ++iewDispSquashedInsts; 1014 1015 insts_to_dispatch.pop(); 1016 1017 //Tell Rename That An Instruction has been processed 1018 if (inst->isLoad() || inst->isStore()) { 1019 toRename->iewInfo[tid].dispatchedToLSQ++; 1020 } 1021 toRename->iewInfo[tid].dispatched++; 1022 1023 continue; 1024 } 1025 1026 // Check for full conditions. 1027 if (instQueue.isFull(tid)) { 1028 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1029 1030 // Call function to start blocking. 1031 block(tid); 1032 1033 // Set unblock to false. Special case where we are using 1034 // skidbuffer (unblocking) instructions but then we still 1035 // get full in the IQ. 1036 toRename->iewUnblock[tid] = false; 1037 1038 ++iewIQFullEvents; 1039 break; 1040 } else if (ldstQueue.isFull(tid)) { 1041 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1042 1043 // Call function to start blocking. 1044 block(tid); 1045 1046 // Set unblock to false. Special case where we are using 1047 // skidbuffer (unblocking) instructions but then we still 1048 // get full in the IQ. 1049 toRename->iewUnblock[tid] = false; 1050 1051 ++iewLSQFullEvents; 1052 break; 1053 } 1054 1055 // Otherwise issue the instruction just fine. 1056 if (inst->isLoad()) { 1057 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1058 "encountered, adding to LSQ.\n", tid); 1059 1060 // Reserve a spot in the load store queue for this 1061 // memory access. 1062 ldstQueue.insertLoad(inst); 1063 1064 ++iewDispLoadInsts; 1065 1066 add_to_iq = true; 1067 1068 toRename->iewInfo[tid].dispatchedToLSQ++; 1069 } else if (inst->isStore()) { 1070 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1071 "encountered, adding to LSQ.\n", tid); 1072 1073 ldstQueue.insertStore(inst); 1074 1075 ++iewDispStoreInsts; 1076 1077 if (inst->isStoreConditional()) { 1078 // Store conditionals need to be set as "canCommit()" 1079 // so that commit can process them when they reach the 1080 // head of commit. 1081 // @todo: This is somewhat specific to Alpha. 1082 inst->setCanCommit(); 1083 instQueue.insertNonSpec(inst); 1084 add_to_iq = false; 1085 1086 ++iewDispNonSpecInsts; 1087 } else { 1088 add_to_iq = true; 1089 } 1090 1091 toRename->iewInfo[tid].dispatchedToLSQ++; 1092 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1093 // Same as non-speculative stores. 1094 inst->setCanCommit(); 1095 instQueue.insertBarrier(inst); 1096 add_to_iq = false; 1097 } else if (inst->isNop()) { 1098 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1099 "skipping.\n", tid); 1100 1101 inst->setIssued(); 1102 inst->setExecuted(); 1103 inst->setCanCommit(); 1104 1105 instQueue.recordProducer(inst); 1106 1107 iewExecutedNop[tid]++; 1108 1109 add_to_iq = false; 1110 } else if (inst->isExecuted()) { 1111 assert(0 && "Instruction shouldn't be executed.\n"); 1112 DPRINTF(IEW, "Issue: Executed branch encountered, " 1113 "skipping.\n"); 1114 1115 inst->setIssued(); 1116 inst->setCanCommit(); 1117 1118 instQueue.recordProducer(inst); 1119 1120 add_to_iq = false; 1121 } else { 1122 add_to_iq = true; 1123 } 1124 if (inst->isNonSpeculative()) { 1125 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1126 "encountered, skipping.\n", tid); 1127 1128 // Same as non-speculative stores. 1129 inst->setCanCommit(); 1130 1131 // Specifically insert it as nonspeculative. 1132 instQueue.insertNonSpec(inst); 1133 1134 ++iewDispNonSpecInsts; 1135 1136 add_to_iq = false; 1137 } 1138 1139 // If the instruction queue is not full, then add the 1140 // instruction. 1141 if (add_to_iq) { 1142 instQueue.insert(inst); 1143 } 1144 1145 insts_to_dispatch.pop(); 1146 1147 toRename->iewInfo[tid].dispatched++; 1148 1149 ++iewDispatchedInsts; 1150 1151#if TRACING_ON 1152 inst->dispatchTick = curTick(); 1153#endif 1154 } 1155 1156 if (!insts_to_dispatch.empty()) { 1157 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); 1158 block(tid); 1159 toRename->iewUnblock[tid] = false; 1160 } 1161 1162 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1163 dispatchStatus[tid] = Running; 1164 1165 updatedQueues = true; 1166 } 1167 1168 dis_num_inst = 0; 1169} 1170 1171template <class Impl> 1172void 1173DefaultIEW<Impl>::printAvailableInsts() 1174{ 1175 int inst = 0; 1176 1177 std::cout << "Available Instructions: "; 1178 1179 while (fromIssue->insts[inst]) { 1180 1181 if (inst%3==0) std::cout << "\n\t"; 1182 1183 std::cout << "PC: " << fromIssue->insts[inst]->pcState() 1184 << " TN: " << fromIssue->insts[inst]->threadNumber 1185 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1186 1187 inst++; 1188 1189 } 1190 1191 std::cout << "\n"; 1192} 1193 1194template <class Impl> 1195void 1196DefaultIEW<Impl>::executeInsts() 1197{ 1198 wbNumInst = 0; 1199 wbCycle = 0; 1200 1201 list<ThreadID>::iterator threads = activeThreads->begin(); 1202 list<ThreadID>::iterator end = activeThreads->end(); 1203 1204 while (threads != end) { 1205 ThreadID tid = *threads++; 1206 fetchRedirect[tid] = false; 1207 } 1208 1209 // Uncomment this if you want to see all available instructions. 1210 // @todo This doesn't actually work anymore, we should fix it. 1211// printAvailableInsts(); 1212 1213 // Execute/writeback any instructions that are available. 1214 int insts_to_execute = fromIssue->size; 1215 int inst_num = 0; 1216 for (; inst_num < insts_to_execute; 1217 ++inst_num) { 1218 1219 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1220 1221 DynInstPtr inst = instQueue.getInstToExecute(); 1222 1223 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", 1224 inst->pcState(), inst->threadNumber,inst->seqNum); 1225 1226 // Check if the instruction is squashed; if so then skip it 1227 if (inst->isSquashed()) { 1228 DPRINTF(IEW, "Execute: Instruction was squashed. PC: %s, [tid:%i]" 1229 " [sn:%i]\n", inst->pcState(), inst->threadNumber, 1230 inst->seqNum); 1231 1232 // Consider this instruction executed so that commit can go 1233 // ahead and retire the instruction. 1234 inst->setExecuted(); 1235 1236 // Not sure if I should set this here or just let commit try to 1237 // commit any squashed instructions. I like the latter a bit more. 1238 inst->setCanCommit(); 1239 1240 ++iewExecSquashedInsts; 1241 1242 decrWb(inst->seqNum); 1243 continue; 1244 } 1245 1246 Fault fault = NoFault; 1247 1248 // Execute instruction. 1249 // Note that if the instruction faults, it will be handled 1250 // at the commit stage. 1251 if (inst->isMemRef()) { 1252 DPRINTF(IEW, "Execute: Calculating address for memory " 1253 "reference.\n"); 1254 1255 // Tell the LDSTQ to execute this instruction (if it is a load). 1256 if (inst->isLoad()) { 1257 // Loads will mark themselves as executed, and their writeback 1258 // event adds the instruction to the queue to commit 1259 fault = ldstQueue.executeLoad(inst); 1260 1261 if (inst->isTranslationDelayed() && 1262 fault == NoFault) { 1263 // A hw page table walk is currently going on; the 1264 // instruction must be deferred. 1265 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1266 "load.\n"); 1267 instQueue.deferMemInst(inst); 1268 continue; 1269 } 1270 1271 if (inst->isDataPrefetch() || inst->isInstPrefetch()) { 1272 inst->fault = NoFault; 1273 } 1274 } else if (inst->isStore()) { 1275 fault = ldstQueue.executeStore(inst); 1276 1277 if (inst->isTranslationDelayed() && 1278 fault == NoFault) { 1279 // A hw page table walk is currently going on; the 1280 // instruction must be deferred. 1281 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1282 "store.\n"); 1283 instQueue.deferMemInst(inst); 1284 continue; 1285 } 1286 1287 // If the store had a fault then it may not have a mem req 1288 if (fault != NoFault || inst->readPredicate() == false || 1289 !inst->isStoreConditional()) { 1290 // If the instruction faulted, then we need to send it along 1291 // to commit without the instruction completing. 1292 // Send this instruction to commit, also make sure iew stage 1293 // realizes there is activity. 1294 inst->setExecuted(); 1295 instToCommit(inst); 1296 activityThisCycle(); 1297 } 1298 1299 // Store conditionals will mark themselves as 1300 // executed, and their writeback event will add the 1301 // instruction to the queue to commit. 1302 } else { 1303 panic("Unexpected memory type!\n"); 1304 } 1305 1306 } else { 1307 // If the instruction has already faulted, then skip executing it. 1308 // Such case can happen when it faulted during ITLB translation. 1309 // If we execute the instruction (even if it's a nop) the fault 1310 // will be replaced and we will lose it. 1311 if (inst->getFault() == NoFault) { 1312 inst->execute(); 1313 if (inst->readPredicate() == false) 1314 inst->forwardOldRegs(); 1315 } 1316 1317 inst->setExecuted(); 1318 1319 instToCommit(inst); 1320 } 1321 1322 updateExeInstStats(inst); 1323 1324 // Check if branch prediction was correct, if not then we need 1325 // to tell commit to squash in flight instructions. Only 1326 // handle this if there hasn't already been something that 1327 // redirects fetch in this group of instructions. 1328 1329 // This probably needs to prioritize the redirects if a different 1330 // scheduler is used. Currently the scheduler schedules the oldest 1331 // instruction first, so the branch resolution order will be correct. 1332 ThreadID tid = inst->threadNumber; 1333 1334 if (!fetchRedirect[tid] || 1335 !toCommit->squash[tid] || 1336 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1337 1338 // Prevent testing for misprediction on load instructions, 1339 // that have not been executed. 1340 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad(); 1341 1342 if (inst->mispredicted() && !loadNotExecuted) { 1343 fetchRedirect[tid] = true; 1344 1345 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1346 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1347 inst->predInstAddr(), inst->predNextInstAddr()); 1348 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", 1349 inst->pcState(), inst->nextInstAddr()); 1350 // If incorrect, then signal the ROB that it must be squashed. 1351 squashDueToBranch(inst, tid); 1352 1353 if (inst->readPredTaken()) { 1354 predictedTakenIncorrect++; 1355 } else { 1356 predictedNotTakenIncorrect++; 1357 } 1358 } else if (ldstQueue.violation(tid)) { 1359 assert(inst->isMemRef()); 1360 // If there was an ordering violation, then get the 1361 // DynInst that caused the violation. Note that this 1362 // clears the violation signal. 1363 DynInstPtr violator; 1364 violator = ldstQueue.getMemDepViolator(tid); 1365 1366 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " 1367 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", 1368 violator->pcState(), violator->seqNum, 1369 inst->pcState(), inst->seqNum, inst->physEffAddr); 1370 1371 fetchRedirect[tid] = true; 1372 1373 // Tell the instruction queue that a violation has occured. 1374 instQueue.violation(inst, violator); 1375 1376 // Squash. 1377 squashDueToMemOrder(inst,tid); 1378 1379 ++memOrderViolationEvents; 1380 } else if (ldstQueue.loadBlocked(tid) && 1381 !ldstQueue.isLoadBlockedHandled(tid)) { 1382 fetchRedirect[tid] = true; 1383 1384 DPRINTF(IEW, "Load operation couldn't execute because the " 1385 "memory system is blocked. PC: %s [sn:%lli]\n", 1386 inst->pcState(), inst->seqNum); 1387 1388 squashDueToMemBlocked(inst, tid); 1389 } 1390 } else { 1391 // Reset any state associated with redirects that will not 1392 // be used. 1393 if (ldstQueue.violation(tid)) { 1394 assert(inst->isMemRef()); 1395 1396 DynInstPtr violator = ldstQueue.getMemDepViolator(tid); 1397 1398 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1399 "%s, inst PC: %s. Addr is: %#x.\n", 1400 violator->pcState(), inst->pcState(), 1401 inst->physEffAddr); 1402 DPRINTF(IEW, "Violation will not be handled because " 1403 "already squashing\n"); 1404 1405 ++memOrderViolationEvents; 1406 } 1407 if (ldstQueue.loadBlocked(tid) && 1408 !ldstQueue.isLoadBlockedHandled(tid)) { 1409 DPRINTF(IEW, "Load operation couldn't execute because the " 1410 "memory system is blocked. PC: %s [sn:%lli]\n", 1411 inst->pcState(), inst->seqNum); 1412 DPRINTF(IEW, "Blocked load will not be handled because " 1413 "already squashing\n"); 1414 1415 ldstQueue.setLoadBlockedHandled(tid); 1416 } 1417 1418 } 1419 } 1420 1421 // Update and record activity if we processed any instructions. 1422 if (inst_num) { 1423 if (exeStatus == Idle) { 1424 exeStatus = Running; 1425 } 1426 1427 updatedQueues = true; 1428 1429 cpu->activityThisCycle(); 1430 } 1431 1432 // Need to reset this in case a writeback event needs to write into the 1433 // iew queue. That way the writeback event will write into the correct 1434 // spot in the queue. 1435 wbNumInst = 0; 1436 1437} 1438 1439template <class Impl> 1440void 1441DefaultIEW<Impl>::writebackInsts() 1442{ 1443 // Loop through the head of the time buffer and wake any 1444 // dependents. These instructions are about to write back. Also 1445 // mark scoreboard that this instruction is finally complete. 1446 // Either have IEW have direct access to scoreboard, or have this 1447 // as part of backwards communication. 1448 for (int inst_num = 0; inst_num < wbWidth && 1449 toCommit->insts[inst_num]; inst_num++) { 1450 DynInstPtr inst = toCommit->insts[inst_num]; 1451 ThreadID tid = inst->threadNumber; 1452 1453 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", 1454 inst->seqNum, inst->pcState()); 1455 1456 iewInstsToCommit[tid]++; 1457 1458 // Some instructions will be sent to commit without having 1459 // executed because they need commit to handle them. 1460 // E.g. Uncached loads have not actually executed when they 1461 // are first sent to commit. Instead commit must tell the LSQ 1462 // when it's ready to execute the uncached load. 1463 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { 1464 int dependents = instQueue.wakeDependents(inst); 1465 1466 for (int i = 0; i < inst->numDestRegs(); i++) { 1467 //mark as Ready 1468 DPRINTF(IEW,"Setting Destination Register %i\n", 1469 inst->renamedDestRegIdx(i)); 1470 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1471 } 1472 1473 if (dependents) { 1474 producerInst[tid]++; 1475 consumerInst[tid]+= dependents; 1476 } 1477 writebackCount[tid]++; 1478 } 1479 1480 decrWb(inst->seqNum); 1481 } 1482} 1483 1484template<class Impl> 1485void 1486DefaultIEW<Impl>::tick() 1487{ 1488 wbNumInst = 0; 1489 wbCycle = 0; 1490 1491 wroteToTimeBuffer = false; 1492 updatedQueues = false; 1493 1494 sortInsts(); 1495 1496 // Free function units marked as being freed this cycle. 1497 fuPool->processFreeUnits(); 1498 1499 list<ThreadID>::iterator threads = activeThreads->begin(); 1500 list<ThreadID>::iterator end = activeThreads->end(); 1501 1502 // Check stall and squash signals, dispatch any instructions. 1503 while (threads != end) { 1504 ThreadID tid = *threads++; 1505 1506 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1507 1508 checkSignalsAndUpdate(tid); 1509 dispatch(tid); 1510 } 1511 1512 if (exeStatus != Squashing) { 1513 executeInsts(); 1514 1515 writebackInsts(); 1516 1517 // Have the instruction queue try to schedule any ready instructions. 1518 // (In actuality, this scheduling is for instructions that will 1519 // be executed next cycle.) 1520 instQueue.scheduleReadyInsts(); 1521 1522 // Also should advance its own time buffers if the stage ran. 1523 // Not the best place for it, but this works (hopefully). 1524 issueToExecQueue.advance(); 1525 } 1526 1527 bool broadcast_free_entries = false; 1528 1529 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1530 exeStatus = Idle; 1531 updateLSQNextCycle = false; 1532 1533 broadcast_free_entries = true; 1534 } 1535 1536 // Writeback any stores using any leftover bandwidth. 1537 ldstQueue.writebackStores(); 1538 1539 // Check the committed load/store signals to see if there's a load 1540 // or store to commit. Also check if it's being told to execute a 1541 // nonspeculative instruction. 1542 // This is pretty inefficient... 1543 1544 threads = activeThreads->begin(); 1545 while (threads != end) { 1546 ThreadID tid = (*threads++); 1547 1548 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1549 1550 // Update structures based on instructions committed. 1551 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1552 !fromCommit->commitInfo[tid].squash && 1553 !fromCommit->commitInfo[tid].robSquashing) { 1554 1555 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1556 1557 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1558 1559 updateLSQNextCycle = true; 1560 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1561 } 1562 1563 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1564 1565 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1566 if (fromCommit->commitInfo[tid].uncached) { 1567 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1568 fromCommit->commitInfo[tid].uncachedLoad->setAtCommit(); 1569 } else { 1570 instQueue.scheduleNonSpec( 1571 fromCommit->commitInfo[tid].nonSpecSeqNum); 1572 } 1573 } 1574 1575 if (broadcast_free_entries) { 1576 toFetch->iewInfo[tid].iqCount = 1577 instQueue.getCount(tid); 1578 toFetch->iewInfo[tid].ldstqCount = 1579 ldstQueue.getCount(tid); 1580 1581 toRename->iewInfo[tid].usedIQ = true; 1582 toRename->iewInfo[tid].freeIQEntries = 1583 instQueue.numFreeEntries(); 1584 toRename->iewInfo[tid].usedLSQ = true; 1585 toRename->iewInfo[tid].freeLSQEntries = 1586 ldstQueue.numFreeEntries(tid); 1587 1588 wroteToTimeBuffer = true; 1589 } 1590 1591 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1592 tid, toRename->iewInfo[tid].dispatched); 1593 } 1594 1595 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1596 "LSQ has %i free entries.\n", 1597 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1598 ldstQueue.numFreeEntries()); 1599 1600 updateStatus(); 1601 1602 if (wroteToTimeBuffer) { 1603 DPRINTF(Activity, "Activity this cycle.\n"); 1604 cpu->activityThisCycle(); 1605 } 1606} 1607 1608template <class Impl> 1609void 1610DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1611{ 1612 ThreadID tid = inst->threadNumber; 1613 1614 // 1615 // Pick off the software prefetches 1616 // 1617#ifdef TARGET_ALPHA 1618 if (inst->isDataPrefetch()) 1619 iewExecutedSwp[tid]++; 1620 else 1621 iewIewExecutedcutedInsts++; 1622#else 1623 iewExecutedInsts++; 1624#endif 1625 1626#if TRACING_ON 1627 inst->completeTick = curTick(); 1628#endif 1629 1630 // 1631 // Control operations 1632 // 1633 if (inst->isControl()) 1634 iewExecutedBranches[tid]++; 1635 1636 // 1637 // Memory operations 1638 // 1639 if (inst->isMemRef()) { 1640 iewExecutedRefs[tid]++; 1641 1642 if (inst->isLoad()) { 1643 iewExecLoadInsts[tid]++; 1644 } 1645 } 1646} 1647 1648template <class Impl> 1649void 1650DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) 1651{ 1652 ThreadID tid = inst->threadNumber; 1653 1654 if (!fetchRedirect[tid] || 1655 !toCommit->squash[tid] || 1656 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1657 1658 if (inst->mispredicted()) { 1659 fetchRedirect[tid] = true; 1660 1661 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1662 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1663 inst->predInstAddr(), inst->predNextInstAddr()); 1664 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," 1665 " NPC: %#x.\n", inst->nextInstAddr(), 1666 inst->nextInstAddr()); 1667 // If incorrect, then signal the ROB that it must be squashed. 1668 squashDueToBranch(inst, tid); 1669 1670 if (inst->readPredTaken()) { 1671 predictedTakenIncorrect++; 1672 } else { 1673 predictedNotTakenIncorrect++; 1674 } 1675 } 1676 } 1677} 1678