iew_impl.hh revision 9937:49a534f54e72
12735Sktlim@umich.edu/* 212109SRekai.GonzalezAlberquilla@arm.com * Copyright (c) 2010-2013 ARM Limited 310319SAndreas.Sandberg@ARM.com * All rights reserved. 410319SAndreas.Sandberg@ARM.com * 510319SAndreas.Sandberg@ARM.com * The license below extends only to copyright in the software and shall 610319SAndreas.Sandberg@ARM.com * not be construed as granting a license to any other intellectual 710319SAndreas.Sandberg@ARM.com * property including but not limited to intellectual property relating 810319SAndreas.Sandberg@ARM.com * to a hardware implementation of the functionality of the software 910319SAndreas.Sandberg@ARM.com * licensed hereunder. You may use the software subject to the license 1010319SAndreas.Sandberg@ARM.com * terms below provided that you ensure that this notice is replicated 1110319SAndreas.Sandberg@ARM.com * unmodified and in its entirety in all distributions of the software, 1210319SAndreas.Sandberg@ARM.com * modified or unmodified, in source code or in binary form. 1310319SAndreas.Sandberg@ARM.com * 142735Sktlim@umich.edu * Copyright (c) 2004-2006 The Regents of The University of Michigan 1511303Ssteve.reinhardt@amd.com * All rights reserved. 162735Sktlim@umich.edu * 172735Sktlim@umich.edu * Redistribution and use in source and binary forms, with or without 182735Sktlim@umich.edu * modification, are permitted provided that the following conditions are 192735Sktlim@umich.edu * met: redistributions of source code must retain the above copyright 202735Sktlim@umich.edu * notice, this list of conditions and the following disclaimer; 212735Sktlim@umich.edu * redistributions in binary form must reproduce the above copyright 222735Sktlim@umich.edu * notice, this list of conditions and the following disclaimer in the 232735Sktlim@umich.edu * documentation and/or other materials provided with the distribution; 242735Sktlim@umich.edu * neither the name of the copyright holders nor the names of its 252735Sktlim@umich.edu * contributors may be used to endorse or promote products derived from 262735Sktlim@umich.edu * this software without specific prior written permission. 272735Sktlim@umich.edu * 282735Sktlim@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292735Sktlim@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302735Sktlim@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312735Sktlim@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322735Sktlim@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332735Sktlim@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342735Sktlim@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352735Sktlim@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362735Sktlim@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372735Sktlim@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382735Sktlim@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392735Sktlim@umich.edu * 402735Sktlim@umich.edu * Authors: Kevin Lim 412735Sktlim@umich.edu */ 4210319SAndreas.Sandberg@ARM.com 432735Sktlim@umich.edu// @todo: Fix the instantaneous communication among all the stages within 442735Sktlim@umich.edu// iew. There's a clear delay between issue and execute, yet backwards 4510319SAndreas.Sandberg@ARM.com// communication happens simultaneously. 4610319SAndreas.Sandberg@ARM.com 4710319SAndreas.Sandberg@ARM.com#include <queue> 4810319SAndreas.Sandberg@ARM.com 4910319SAndreas.Sandberg@ARM.com#include "arch/utility.hh" 5010319SAndreas.Sandberg@ARM.com#include "config/the_isa.hh" 5110529Smorr@cs.wisc.edu#include "cpu/checker/cpu.hh" 5212104Snathanael.premillieu@arm.com#include "cpu/o3/fu_pool.hh" 5310319SAndreas.Sandberg@ARM.com#include "cpu/o3/iew.hh" 5410319SAndreas.Sandberg@ARM.com#include "cpu/timebuf.hh" 5511608Snikos.nikoleris@arm.com#include "debug/Activity.hh" 562735Sktlim@umich.edu#include "debug/Drain.hh" 572735Sktlim@umich.edu#include "debug/IEW.hh" 5810319SAndreas.Sandberg@ARM.com#include "debug/O3PipeView.hh" 5910319SAndreas.Sandberg@ARM.com#include "params/DerivO3CPU.hh" 6010319SAndreas.Sandberg@ARM.com 6110319SAndreas.Sandberg@ARM.comusing namespace std; 6210319SAndreas.Sandberg@ARM.com 6310319SAndreas.Sandberg@ARM.comtemplate<class Impl> 6410319SAndreas.Sandberg@ARM.comDefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, DerivO3CPUParams *params) 6510319SAndreas.Sandberg@ARM.com : issueToExecQueue(params->backComSize, params->forwardComSize), 6610319SAndreas.Sandberg@ARM.com cpu(_cpu), 6710319SAndreas.Sandberg@ARM.com instQueue(_cpu, this, params), 6810319SAndreas.Sandberg@ARM.com ldstQueue(_cpu, this, params), 6910319SAndreas.Sandberg@ARM.com fuPool(params->fuPool), 7010319SAndreas.Sandberg@ARM.com commitToIEWDelay(params->commitToIEWDelay), 7110319SAndreas.Sandberg@ARM.com renameToIEWDelay(params->renameToIEWDelay), 722735Sktlim@umich.edu issueToExecuteDelay(params->issueToExecuteDelay), 732735Sktlim@umich.edu dispatchWidth(params->dispatchWidth), 7410319SAndreas.Sandberg@ARM.com issueWidth(params->issueWidth), 7510319SAndreas.Sandberg@ARM.com wbOutstanding(0), 7610319SAndreas.Sandberg@ARM.com wbWidth(params->wbWidth), 7710319SAndreas.Sandberg@ARM.com numThreads(params->numThreads) 7812109SRekai.GonzalezAlberquilla@arm.com{ 7912109SRekai.GonzalezAlberquilla@arm.com _status = Active; 8010319SAndreas.Sandberg@ARM.com exeStatus = Running; 8110319SAndreas.Sandberg@ARM.com wbStatus = Idle; 8210319SAndreas.Sandberg@ARM.com 8310319SAndreas.Sandberg@ARM.com // Setup wire to read instructions coming from issue. 8410319SAndreas.Sandberg@ARM.com fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay); 8510319SAndreas.Sandberg@ARM.com 8610319SAndreas.Sandberg@ARM.com // Instruction queue needs the queue between issue and execute. 872735Sktlim@umich.edu instQueue.setIssueToExecuteQueue(&issueToExecQueue); 882735Sktlim@umich.edu 8913557Sgabeblack@google.com for (ThreadID tid = 0; tid < numThreads; tid++) { 9010319SAndreas.Sandberg@ARM.com dispatchStatus[tid] = Running; 9110319SAndreas.Sandberg@ARM.com stalls[tid].commit = false; 9210319SAndreas.Sandberg@ARM.com fetchRedirect[tid] = false; 9313557Sgabeblack@google.com } 9410319SAndreas.Sandberg@ARM.com 9510319SAndreas.Sandberg@ARM.com wbMax = wbWidth * params->wbDepth; 9610319SAndreas.Sandberg@ARM.com 9710319SAndreas.Sandberg@ARM.com updateLSQNextCycle = false; 9810319SAndreas.Sandberg@ARM.com 9910319SAndreas.Sandberg@ARM.com ableToIssue = true; 10010319SAndreas.Sandberg@ARM.com 10110319SAndreas.Sandberg@ARM.com skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth; 1022735Sktlim@umich.edu} 1032735Sktlim@umich.edu 1042735Sktlim@umich.edutemplate <class Impl> 10513557Sgabeblack@google.comstd::string 1062735Sktlim@umich.eduDefaultIEW<Impl>::name() const 1072735Sktlim@umich.edu{ 1082735Sktlim@umich.edu return cpu->name() + ".iew"; 10910319SAndreas.Sandberg@ARM.com} 11013557Sgabeblack@google.com 1112735Sktlim@umich.edutemplate <class Impl> 11210319SAndreas.Sandberg@ARM.comvoid 1132735Sktlim@umich.eduDefaultIEW<Impl>::regStats() 11412109SRekai.GonzalezAlberquilla@arm.com{ 11512109SRekai.GonzalezAlberquilla@arm.com using namespace Stats; 11612109SRekai.GonzalezAlberquilla@arm.com 11712109SRekai.GonzalezAlberquilla@arm.com instQueue.regStats(); 11812109SRekai.GonzalezAlberquilla@arm.com ldstQueue.regStats(); 11912109SRekai.GonzalezAlberquilla@arm.com 12012109SRekai.GonzalezAlberquilla@arm.com iewIdleCycles 12112109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewIdleCycles") 12212109SRekai.GonzalezAlberquilla@arm.com .desc("Number of cycles IEW is idle"); 12312109SRekai.GonzalezAlberquilla@arm.com 12412109SRekai.GonzalezAlberquilla@arm.com iewSquashCycles 12512109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewSquashCycles") 12612109SRekai.GonzalezAlberquilla@arm.com .desc("Number of cycles IEW is squashing"); 12712109SRekai.GonzalezAlberquilla@arm.com 12812109SRekai.GonzalezAlberquilla@arm.com iewBlockCycles 12912109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewBlockCycles") 13012109SRekai.GonzalezAlberquilla@arm.com .desc("Number of cycles IEW is blocking"); 13112109SRekai.GonzalezAlberquilla@arm.com 13212109SRekai.GonzalezAlberquilla@arm.com iewUnblockCycles 13312109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewUnblockCycles") 13412109SRekai.GonzalezAlberquilla@arm.com .desc("Number of cycles IEW is unblocking"); 13512109SRekai.GonzalezAlberquilla@arm.com 13612109SRekai.GonzalezAlberquilla@arm.com iewDispatchedInsts 13712109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispatchedInsts") 13812109SRekai.GonzalezAlberquilla@arm.com .desc("Number of instructions dispatched to IQ"); 13912109SRekai.GonzalezAlberquilla@arm.com 14012109SRekai.GonzalezAlberquilla@arm.com iewDispSquashedInsts 14112109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispSquashedInsts") 14212109SRekai.GonzalezAlberquilla@arm.com .desc("Number of squashed instructions skipped by dispatch"); 14312109SRekai.GonzalezAlberquilla@arm.com 14412109SRekai.GonzalezAlberquilla@arm.com iewDispLoadInsts 14512109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispLoadInsts") 14612109SRekai.GonzalezAlberquilla@arm.com .desc("Number of dispatched load instructions"); 14712109SRekai.GonzalezAlberquilla@arm.com 14812109SRekai.GonzalezAlberquilla@arm.com iewDispStoreInsts 14912109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispStoreInsts") 15012109SRekai.GonzalezAlberquilla@arm.com .desc("Number of dispatched store instructions"); 15112109SRekai.GonzalezAlberquilla@arm.com 15212109SRekai.GonzalezAlberquilla@arm.com iewDispNonSpecInsts 15312109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewDispNonSpecInsts") 15412109SRekai.GonzalezAlberquilla@arm.com .desc("Number of dispatched non-speculative instructions"); 15512109SRekai.GonzalezAlberquilla@arm.com 15612109SRekai.GonzalezAlberquilla@arm.com iewIQFullEvents 15712109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewIQFullEvents") 15812109SRekai.GonzalezAlberquilla@arm.com .desc("Number of times the IQ has become full, causing a stall"); 15912109SRekai.GonzalezAlberquilla@arm.com 16012109SRekai.GonzalezAlberquilla@arm.com iewLSQFullEvents 16112109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".iewLSQFullEvents") 16212109SRekai.GonzalezAlberquilla@arm.com .desc("Number of times the LSQ has become full, causing a stall"); 16312109SRekai.GonzalezAlberquilla@arm.com 16412109SRekai.GonzalezAlberquilla@arm.com memOrderViolationEvents 16512109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".memOrderViolationEvents") 16612109SRekai.GonzalezAlberquilla@arm.com .desc("Number of memory order violations"); 16712109SRekai.GonzalezAlberquilla@arm.com 16812109SRekai.GonzalezAlberquilla@arm.com predictedTakenIncorrect 16912109SRekai.GonzalezAlberquilla@arm.com .name(name() + ".predictedTakenIncorrect") 17012109SRekai.GonzalezAlberquilla@arm.com .desc("Number of branches that were predicted taken incorrectly"); 17110319SAndreas.Sandberg@ARM.com 17210319SAndreas.Sandberg@ARM.com predictedNotTakenIncorrect 17310319SAndreas.Sandberg@ARM.com .name(name() + ".predictedNotTakenIncorrect") 17410319SAndreas.Sandberg@ARM.com .desc("Number of branches that were predicted not taken incorrectly"); 17510319SAndreas.Sandberg@ARM.com 17610319SAndreas.Sandberg@ARM.com branchMispredicts 17710319SAndreas.Sandberg@ARM.com .name(name() + ".branchMispredicts") 1782735Sktlim@umich.edu .desc("Number of branch mispredicts detected at execute"); 17910319SAndreas.Sandberg@ARM.com 18010319SAndreas.Sandberg@ARM.com branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect; 18110319SAndreas.Sandberg@ARM.com 18210319SAndreas.Sandberg@ARM.com iewExecutedInsts 18313557Sgabeblack@google.com .name(name() + ".iewExecutedInsts") 18410319SAndreas.Sandberg@ARM.com .desc("Number of executed instructions"); 18513582Sgabeblack@google.com 1862735Sktlim@umich.edu iewExecLoadInsts 18710319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 18810319SAndreas.Sandberg@ARM.com .name(name() + ".iewExecLoadInsts") 18910319SAndreas.Sandberg@ARM.com .desc("Number of load instructions executed") 19010319SAndreas.Sandberg@ARM.com .flags(total); 19113557Sgabeblack@google.com 1922735Sktlim@umich.edu iewExecSquashedInsts 19310319SAndreas.Sandberg@ARM.com .name(name() + ".iewExecSquashedInsts") 19410319SAndreas.Sandberg@ARM.com .desc("Number of squashed instructions skipped in execute"); 19510319SAndreas.Sandberg@ARM.com 19610319SAndreas.Sandberg@ARM.com iewExecutedSwp 19713582Sgabeblack@google.com .init(cpu->numThreads) 1982735Sktlim@umich.edu .name(name() + ".exec_swp") 19910319SAndreas.Sandberg@ARM.com .desc("number of swp insts executed") 2002735Sktlim@umich.edu .flags(total); 20110319SAndreas.Sandberg@ARM.com 20210319SAndreas.Sandberg@ARM.com iewExecutedNop 20310319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 20410319SAndreas.Sandberg@ARM.com .name(name() + ".exec_nop") 20510319SAndreas.Sandberg@ARM.com .desc("number of nop insts executed") 20610319SAndreas.Sandberg@ARM.com .flags(total); 20710319SAndreas.Sandberg@ARM.com 20810319SAndreas.Sandberg@ARM.com iewExecutedRefs 20910319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 21010319SAndreas.Sandberg@ARM.com .name(name() + ".exec_refs") 21110319SAndreas.Sandberg@ARM.com .desc("number of memory reference insts executed") 21210319SAndreas.Sandberg@ARM.com .flags(total); 21310319SAndreas.Sandberg@ARM.com 21411303Ssteve.reinhardt@amd.com iewExecutedBranches 21511303Ssteve.reinhardt@amd.com .init(cpu->numThreads) 21611303Ssteve.reinhardt@amd.com .name(name() + ".exec_branches") 21711303Ssteve.reinhardt@amd.com .desc("Number of branches executed") 21811303Ssteve.reinhardt@amd.com .flags(total); 21911303Ssteve.reinhardt@amd.com 22010319SAndreas.Sandberg@ARM.com iewExecStoreInsts 22111608Snikos.nikoleris@arm.com .name(name() + ".exec_stores") 22211303Ssteve.reinhardt@amd.com .desc("Number of stores executed") 22311303Ssteve.reinhardt@amd.com .flags(total); 22411303Ssteve.reinhardt@amd.com iewExecStoreInsts = iewExecutedRefs - iewExecLoadInsts; 22510319SAndreas.Sandberg@ARM.com 22611303Ssteve.reinhardt@amd.com iewExecRate 22711303Ssteve.reinhardt@amd.com .name(name() + ".exec_rate") 22811303Ssteve.reinhardt@amd.com .desc("Inst execution rate") 22911303Ssteve.reinhardt@amd.com .flags(total); 23011303Ssteve.reinhardt@amd.com 23111303Ssteve.reinhardt@amd.com iewExecRate = iewExecutedInsts / cpu->numCycles; 23211303Ssteve.reinhardt@amd.com 23311303Ssteve.reinhardt@amd.com iewInstsToCommit 23411608Snikos.nikoleris@arm.com .init(cpu->numThreads) 23511303Ssteve.reinhardt@amd.com .name(name() + ".wb_sent") 23611303Ssteve.reinhardt@amd.com .desc("cumulative count of insts sent to commit") 23711303Ssteve.reinhardt@amd.com .flags(total); 23811303Ssteve.reinhardt@amd.com 23911303Ssteve.reinhardt@amd.com writebackCount 24011303Ssteve.reinhardt@amd.com .init(cpu->numThreads) 24111303Ssteve.reinhardt@amd.com .name(name() + ".wb_count") 24211303Ssteve.reinhardt@amd.com .desc("cumulative count of insts written-back") 24310319SAndreas.Sandberg@ARM.com .flags(total); 24411608Snikos.nikoleris@arm.com 24510319SAndreas.Sandberg@ARM.com producerInst 24610319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 24710319SAndreas.Sandberg@ARM.com .name(name() + ".wb_producers") 24810319SAndreas.Sandberg@ARM.com .desc("num instructions producing a value") 24910319SAndreas.Sandberg@ARM.com .flags(total); 25010319SAndreas.Sandberg@ARM.com 25110319SAndreas.Sandberg@ARM.com consumerInst 25210319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 25310319SAndreas.Sandberg@ARM.com .name(name() + ".wb_consumers") 25410319SAndreas.Sandberg@ARM.com .desc("num instructions consuming a value") 25510319SAndreas.Sandberg@ARM.com .flags(total); 25610319SAndreas.Sandberg@ARM.com 25710319SAndreas.Sandberg@ARM.com wbPenalized 25810319SAndreas.Sandberg@ARM.com .init(cpu->numThreads) 25910319SAndreas.Sandberg@ARM.com .name(name() + ".wb_penalized") 26010319SAndreas.Sandberg@ARM.com .desc("number of instrctions required to write to 'other' IQ") 26110319SAndreas.Sandberg@ARM.com .flags(total); 26210319SAndreas.Sandberg@ARM.com 26310319SAndreas.Sandberg@ARM.com wbPenalizedRate 26410319SAndreas.Sandberg@ARM.com .name(name() + ".wb_penalized_rate") 26510319SAndreas.Sandberg@ARM.com .desc ("fraction of instructions written-back that wrote to 'other' IQ") 26611877Sbrandon.potter@amd.com .flags(total); 26710319SAndreas.Sandberg@ARM.com 26810319SAndreas.Sandberg@ARM.com wbPenalizedRate = wbPenalized / writebackCount; 2692735Sktlim@umich.edu 2702735Sktlim@umich.edu wbFanout 27110319SAndreas.Sandberg@ARM.com .name(name() + ".wb_fanout") 2722735Sktlim@umich.edu .desc("average fanout of values written-back") 27310319SAndreas.Sandberg@ARM.com .flags(total); 27410319SAndreas.Sandberg@ARM.com 27510319SAndreas.Sandberg@ARM.com wbFanout = producerInst / consumerInst; 27610319SAndreas.Sandberg@ARM.com 2777520Sgblack@eecs.umich.edu wbRate 27810319SAndreas.Sandberg@ARM.com .name(name() + ".wb_rate") 27910319SAndreas.Sandberg@ARM.com .desc("insts written-back per cycle") 28010319SAndreas.Sandberg@ARM.com .flags(total); 28110319SAndreas.Sandberg@ARM.com wbRate = writebackCount / cpu->numCycles; 28210319SAndreas.Sandberg@ARM.com} 2835702Ssaidi@eecs.umich.edu 2845702Ssaidi@eecs.umich.edutemplate<class Impl> 2855702Ssaidi@eecs.umich.eduvoid 2865702Ssaidi@eecs.umich.eduDefaultIEW<Impl>::startupStage() 2875702Ssaidi@eecs.umich.edu{ 28810319SAndreas.Sandberg@ARM.com for (ThreadID tid = 0; tid < numThreads; tid++) { 2898779Sgblack@eecs.umich.edu toRename->iewInfo[tid].usedIQ = true; 29010319SAndreas.Sandberg@ARM.com toRename->iewInfo[tid].freeIQEntries = 2916973Stjones1@inf.ed.ac.uk instQueue.numFreeEntries(tid); 29210319SAndreas.Sandberg@ARM.com 29310319SAndreas.Sandberg@ARM.com toRename->iewInfo[tid].usedLSQ = true; 29410319SAndreas.Sandberg@ARM.com toRename->iewInfo[tid].freeLSQEntries = 29510319SAndreas.Sandberg@ARM.com ldstQueue.numFreeEntries(tid); 29610319SAndreas.Sandberg@ARM.com } 29713429Srekai.gonzalezalberquilla@arm.com 29810319SAndreas.Sandberg@ARM.com // Initialize the checker's dcache port here 29910319SAndreas.Sandberg@ARM.com if (cpu->checker) { 30010319SAndreas.Sandberg@ARM.com cpu->checker->setDcachePort(&cpu->getDataPort()); 30110319SAndreas.Sandberg@ARM.com } 30210319SAndreas.Sandberg@ARM.com 30310319SAndreas.Sandberg@ARM.com cpu->activateStage(O3CPU::IEWIdx); 30410319SAndreas.Sandberg@ARM.com} 30510319SAndreas.Sandberg@ARM.com 30610319SAndreas.Sandberg@ARM.comtemplate<class Impl> 30710319SAndreas.Sandberg@ARM.comvoid 30810319SAndreas.Sandberg@ARM.comDefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr) 30910319SAndreas.Sandberg@ARM.com{ 31010319SAndreas.Sandberg@ARM.com timeBuffer = tb_ptr; 31110529Smorr@cs.wisc.edu 31210529Smorr@cs.wisc.edu // Setup wire to read information from time buffer, from commit. 31310529Smorr@cs.wisc.edu fromCommit = timeBuffer->getWire(-commitToIEWDelay); 31410529Smorr@cs.wisc.edu 31510319SAndreas.Sandberg@ARM.com // Setup wire to write information back to previous stages. 31610319SAndreas.Sandberg@ARM.com toRename = timeBuffer->getWire(0); 31710319SAndreas.Sandberg@ARM.com 31810319SAndreas.Sandberg@ARM.com toFetch = timeBuffer->getWire(0); 31910319SAndreas.Sandberg@ARM.com 32010319SAndreas.Sandberg@ARM.com // Instruction queue also needs main time buffer. 32110319SAndreas.Sandberg@ARM.com instQueue.setTimeBuffer(tb_ptr); 32210319SAndreas.Sandberg@ARM.com} 32310319SAndreas.Sandberg@ARM.com 32413557Sgabeblack@google.comtemplate<class Impl> 32513557Sgabeblack@google.comvoid 32613557Sgabeblack@google.comDefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr) 32713557Sgabeblack@google.com{ 32810319SAndreas.Sandberg@ARM.com renameQueue = rq_ptr; 32910319SAndreas.Sandberg@ARM.com 33010319SAndreas.Sandberg@ARM.com // Setup wire to read information from rename queue. 3312735Sktlim@umich.edu fromRename = renameQueue->getWire(-renameToIEWDelay); 33210319SAndreas.Sandberg@ARM.com} 33310319SAndreas.Sandberg@ARM.com 334template<class Impl> 335void 336DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr) 337{ 338 iewQueue = iq_ptr; 339 340 // Setup wire to write instructions to commit. 341 toCommit = iewQueue->getWire(0); 342} 343 344template<class Impl> 345void 346DefaultIEW<Impl>::setActiveThreads(list<ThreadID> *at_ptr) 347{ 348 activeThreads = at_ptr; 349 350 ldstQueue.setActiveThreads(at_ptr); 351 instQueue.setActiveThreads(at_ptr); 352} 353 354template<class Impl> 355void 356DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr) 357{ 358 scoreboard = sb_ptr; 359} 360 361template <class Impl> 362bool 363DefaultIEW<Impl>::isDrained() const 364{ 365 bool drained(ldstQueue.isDrained()); 366 367 for (ThreadID tid = 0; tid < numThreads; tid++) { 368 if (!insts[tid].empty()) { 369 DPRINTF(Drain, "%i: Insts not empty.\n", tid); 370 drained = false; 371 } 372 if (!skidBuffer[tid].empty()) { 373 DPRINTF(Drain, "%i: Skid buffer not empty.\n", tid); 374 drained = false; 375 } 376 } 377 378 // Also check the FU pool as instructions are "stored" in FU 379 // completion events until they are done and not accounted for 380 // above 381 if (drained && !fuPool->isDrained()) { 382 DPRINTF(Drain, "FU pool still busy.\n"); 383 drained = false; 384 } 385 386 return drained; 387} 388 389template <class Impl> 390void 391DefaultIEW<Impl>::drainSanityCheck() const 392{ 393 assert(isDrained()); 394 395 instQueue.drainSanityCheck(); 396 ldstQueue.drainSanityCheck(); 397} 398 399template <class Impl> 400void 401DefaultIEW<Impl>::takeOverFrom() 402{ 403 // Reset all state. 404 _status = Active; 405 exeStatus = Running; 406 wbStatus = Idle; 407 408 instQueue.takeOverFrom(); 409 ldstQueue.takeOverFrom(); 410 fuPool->takeOverFrom(); 411 412 startupStage(); 413 cpu->activityThisCycle(); 414 415 for (ThreadID tid = 0; tid < numThreads; tid++) { 416 dispatchStatus[tid] = Running; 417 stalls[tid].commit = false; 418 fetchRedirect[tid] = false; 419 } 420 421 updateLSQNextCycle = false; 422 423 for (int i = 0; i < issueToExecQueue.getSize(); ++i) { 424 issueToExecQueue.advance(); 425 } 426} 427 428template<class Impl> 429void 430DefaultIEW<Impl>::squash(ThreadID tid) 431{ 432 DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n", tid); 433 434 // Tell the IQ to start squashing. 435 instQueue.squash(tid); 436 437 // Tell the LDSTQ to start squashing. 438 ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid); 439 updatedQueues = true; 440 441 // Clear the skid buffer in case it has any data in it. 442 DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n", 443 tid, fromCommit->commitInfo[tid].doneSeqNum); 444 445 while (!skidBuffer[tid].empty()) { 446 if (skidBuffer[tid].front()->isLoad() || 447 skidBuffer[tid].front()->isStore() ) { 448 toRename->iewInfo[tid].dispatchedToLSQ++; 449 } 450 451 toRename->iewInfo[tid].dispatched++; 452 453 skidBuffer[tid].pop(); 454 } 455 456 emptyRenameInsts(tid); 457} 458 459template<class Impl> 460void 461DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, ThreadID tid) 462{ 463 DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %s " 464 "[sn:%i].\n", tid, inst->pcState(), inst->seqNum); 465 466 if (toCommit->squash[tid] == false || 467 inst->seqNum < toCommit->squashedSeqNum[tid]) { 468 toCommit->squash[tid] = true; 469 toCommit->squashedSeqNum[tid] = inst->seqNum; 470 toCommit->branchTaken[tid] = inst->pcState().branching(); 471 472 TheISA::PCState pc = inst->pcState(); 473 TheISA::advancePC(pc, inst->staticInst); 474 475 toCommit->pc[tid] = pc; 476 toCommit->mispredictInst[tid] = inst; 477 toCommit->includeSquashInst[tid] = false; 478 479 wroteToTimeBuffer = true; 480 } 481 482} 483 484template<class Impl> 485void 486DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, ThreadID tid) 487{ 488 DPRINTF(IEW, "[tid:%i]: Memory violation, squashing violator and younger " 489 "insts, PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 490 // Need to include inst->seqNum in the following comparison to cover the 491 // corner case when a branch misprediction and a memory violation for the 492 // same instruction (e.g. load PC) are detected in the same cycle. In this 493 // case the memory violator should take precedence over the branch 494 // misprediction because it requires the violator itself to be included in 495 // the squash. 496 if (toCommit->squash[tid] == false || 497 inst->seqNum <= toCommit->squashedSeqNum[tid]) { 498 toCommit->squash[tid] = true; 499 500 toCommit->squashedSeqNum[tid] = inst->seqNum; 501 toCommit->pc[tid] = inst->pcState(); 502 toCommit->mispredictInst[tid] = NULL; 503 504 // Must include the memory violator in the squash. 505 toCommit->includeSquashInst[tid] = true; 506 507 wroteToTimeBuffer = true; 508 } 509} 510 511template<class Impl> 512void 513DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, ThreadID tid) 514{ 515 DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, " 516 "PC: %s [sn:%i].\n", tid, inst->pcState(), inst->seqNum); 517 if (toCommit->squash[tid] == false || 518 inst->seqNum < toCommit->squashedSeqNum[tid]) { 519 toCommit->squash[tid] = true; 520 521 toCommit->squashedSeqNum[tid] = inst->seqNum; 522 toCommit->pc[tid] = inst->pcState(); 523 toCommit->mispredictInst[tid] = NULL; 524 525 // Must include the broadcasted SN in the squash. 526 toCommit->includeSquashInst[tid] = true; 527 528 ldstQueue.setLoadBlockedHandled(tid); 529 530 wroteToTimeBuffer = true; 531 } 532} 533 534template<class Impl> 535void 536DefaultIEW<Impl>::block(ThreadID tid) 537{ 538 DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid); 539 540 if (dispatchStatus[tid] != Blocked && 541 dispatchStatus[tid] != Unblocking) { 542 toRename->iewBlock[tid] = true; 543 wroteToTimeBuffer = true; 544 } 545 546 // Add the current inputs to the skid buffer so they can be 547 // reprocessed when this stage unblocks. 548 skidInsert(tid); 549 550 dispatchStatus[tid] = Blocked; 551} 552 553template<class Impl> 554void 555DefaultIEW<Impl>::unblock(ThreadID tid) 556{ 557 DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid " 558 "buffer %u.\n",tid, tid); 559 560 // If the skid bufffer is empty, signal back to previous stages to unblock. 561 // Also switch status to running. 562 if (skidBuffer[tid].empty()) { 563 toRename->iewUnblock[tid] = true; 564 wroteToTimeBuffer = true; 565 DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid); 566 dispatchStatus[tid] = Running; 567 } 568} 569 570template<class Impl> 571void 572DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst) 573{ 574 instQueue.wakeDependents(inst); 575} 576 577template<class Impl> 578void 579DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst) 580{ 581 instQueue.rescheduleMemInst(inst); 582} 583 584template<class Impl> 585void 586DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst) 587{ 588 instQueue.replayMemInst(inst); 589} 590 591template<class Impl> 592void 593DefaultIEW<Impl>::instToCommit(DynInstPtr &inst) 594{ 595 // This function should not be called after writebackInsts in a 596 // single cycle. That will cause problems with an instruction 597 // being added to the queue to commit without being processed by 598 // writebackInsts prior to being sent to commit. 599 600 // First check the time slot that this instruction will write 601 // to. If there are free write ports at the time, then go ahead 602 // and write the instruction to that time. If there are not, 603 // keep looking back to see where's the first time there's a 604 // free slot. 605 while ((*iewQueue)[wbCycle].insts[wbNumInst]) { 606 ++wbNumInst; 607 if (wbNumInst == wbWidth) { 608 ++wbCycle; 609 wbNumInst = 0; 610 } 611 612 assert((wbCycle * wbWidth + wbNumInst) <= wbMax); 613 } 614 615 DPRINTF(IEW, "Current wb cycle: %i, width: %i, numInst: %i\nwbActual:%i\n", 616 wbCycle, wbWidth, wbNumInst, wbCycle * wbWidth + wbNumInst); 617 // Add finished instruction to queue to commit. 618 (*iewQueue)[wbCycle].insts[wbNumInst] = inst; 619 (*iewQueue)[wbCycle].size++; 620} 621 622template <class Impl> 623unsigned 624DefaultIEW<Impl>::validInstsFromRename() 625{ 626 unsigned inst_count = 0; 627 628 for (int i=0; i<fromRename->size; i++) { 629 if (!fromRename->insts[i]->isSquashed()) 630 inst_count++; 631 } 632 633 return inst_count; 634} 635 636template<class Impl> 637void 638DefaultIEW<Impl>::skidInsert(ThreadID tid) 639{ 640 DynInstPtr inst = NULL; 641 642 while (!insts[tid].empty()) { 643 inst = insts[tid].front(); 644 645 insts[tid].pop(); 646 647 DPRINTF(IEW,"[tid:%i]: Inserting [sn:%lli] PC:%s into " 648 "dispatch skidBuffer %i\n",tid, inst->seqNum, 649 inst->pcState(),tid); 650 651 skidBuffer[tid].push(inst); 652 } 653 654 assert(skidBuffer[tid].size() <= skidBufferMax && 655 "Skidbuffer Exceeded Max Size"); 656} 657 658template<class Impl> 659int 660DefaultIEW<Impl>::skidCount() 661{ 662 int max=0; 663 664 list<ThreadID>::iterator threads = activeThreads->begin(); 665 list<ThreadID>::iterator end = activeThreads->end(); 666 667 while (threads != end) { 668 ThreadID tid = *threads++; 669 unsigned thread_count = skidBuffer[tid].size(); 670 if (max < thread_count) 671 max = thread_count; 672 } 673 674 return max; 675} 676 677template<class Impl> 678bool 679DefaultIEW<Impl>::skidsEmpty() 680{ 681 list<ThreadID>::iterator threads = activeThreads->begin(); 682 list<ThreadID>::iterator end = activeThreads->end(); 683 684 while (threads != end) { 685 ThreadID tid = *threads++; 686 687 if (!skidBuffer[tid].empty()) 688 return false; 689 } 690 691 return true; 692} 693 694template <class Impl> 695void 696DefaultIEW<Impl>::updateStatus() 697{ 698 bool any_unblocking = false; 699 700 list<ThreadID>::iterator threads = activeThreads->begin(); 701 list<ThreadID>::iterator end = activeThreads->end(); 702 703 while (threads != end) { 704 ThreadID tid = *threads++; 705 706 if (dispatchStatus[tid] == Unblocking) { 707 any_unblocking = true; 708 break; 709 } 710 } 711 712 // If there are no ready instructions waiting to be scheduled by the IQ, 713 // and there's no stores waiting to write back, and dispatch is not 714 // unblocking, then there is no internal activity for the IEW stage. 715 instQueue.intInstQueueReads++; 716 if (_status == Active && !instQueue.hasReadyInsts() && 717 !ldstQueue.willWB() && !any_unblocking) { 718 DPRINTF(IEW, "IEW switching to idle\n"); 719 720 deactivateStage(); 721 722 _status = Inactive; 723 } else if (_status == Inactive && (instQueue.hasReadyInsts() || 724 ldstQueue.willWB() || 725 any_unblocking)) { 726 // Otherwise there is internal activity. Set to active. 727 DPRINTF(IEW, "IEW switching to active\n"); 728 729 activateStage(); 730 731 _status = Active; 732 } 733} 734 735template <class Impl> 736void 737DefaultIEW<Impl>::resetEntries() 738{ 739 instQueue.resetEntries(); 740 ldstQueue.resetEntries(); 741} 742 743template <class Impl> 744void 745DefaultIEW<Impl>::readStallSignals(ThreadID tid) 746{ 747 if (fromCommit->commitBlock[tid]) { 748 stalls[tid].commit = true; 749 } 750 751 if (fromCommit->commitUnblock[tid]) { 752 assert(stalls[tid].commit); 753 stalls[tid].commit = false; 754 } 755} 756 757template <class Impl> 758bool 759DefaultIEW<Impl>::checkStall(ThreadID tid) 760{ 761 bool ret_val(false); 762 763 if (stalls[tid].commit) { 764 DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); 765 ret_val = true; 766 } else if (instQueue.isFull(tid)) { 767 DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); 768 ret_val = true; 769 } else if (ldstQueue.isFull(tid)) { 770 DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); 771 772 if (ldstQueue.numLoads(tid) > 0 ) { 773 774 DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n", 775 tid,ldstQueue.getLoadHeadSeqNum(tid)); 776 } 777 778 if (ldstQueue.numStores(tid) > 0) { 779 780 DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n", 781 tid,ldstQueue.getStoreHeadSeqNum(tid)); 782 } 783 784 ret_val = true; 785 } else if (ldstQueue.isStalled(tid)) { 786 DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); 787 ret_val = true; 788 } 789 790 return ret_val; 791} 792 793template <class Impl> 794void 795DefaultIEW<Impl>::checkSignalsAndUpdate(ThreadID tid) 796{ 797 // Check if there's a squash signal, squash if there is 798 // Check stall signals, block if there is. 799 // If status was Blocked 800 // if so then go to unblocking 801 // If status was Squashing 802 // check if squashing is not high. Switch to running this cycle. 803 804 readStallSignals(tid); 805 806 if (fromCommit->commitInfo[tid].squash) { 807 squash(tid); 808 809 if (dispatchStatus[tid] == Blocked || 810 dispatchStatus[tid] == Unblocking) { 811 toRename->iewUnblock[tid] = true; 812 wroteToTimeBuffer = true; 813 } 814 815 dispatchStatus[tid] = Squashing; 816 fetchRedirect[tid] = false; 817 return; 818 } 819 820 if (fromCommit->commitInfo[tid].robSquashing) { 821 DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n", tid); 822 823 dispatchStatus[tid] = Squashing; 824 emptyRenameInsts(tid); 825 wroteToTimeBuffer = true; 826 return; 827 } 828 829 if (checkStall(tid)) { 830 block(tid); 831 dispatchStatus[tid] = Blocked; 832 return; 833 } 834 835 if (dispatchStatus[tid] == Blocked) { 836 // Status from previous cycle was blocked, but there are no more stall 837 // conditions. Switch over to unblocking. 838 DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n", 839 tid); 840 841 dispatchStatus[tid] = Unblocking; 842 843 unblock(tid); 844 845 return; 846 } 847 848 if (dispatchStatus[tid] == Squashing) { 849 // Switch status to running if rename isn't being told to block or 850 // squash this cycle. 851 DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n", 852 tid); 853 854 dispatchStatus[tid] = Running; 855 856 return; 857 } 858} 859 860template <class Impl> 861void 862DefaultIEW<Impl>::sortInsts() 863{ 864 int insts_from_rename = fromRename->size; 865#ifdef DEBUG 866 for (ThreadID tid = 0; tid < numThreads; tid++) 867 assert(insts[tid].empty()); 868#endif 869 for (int i = 0; i < insts_from_rename; ++i) { 870 insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]); 871 } 872} 873 874template <class Impl> 875void 876DefaultIEW<Impl>::emptyRenameInsts(ThreadID tid) 877{ 878 DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid); 879 880 while (!insts[tid].empty()) { 881 882 if (insts[tid].front()->isLoad() || 883 insts[tid].front()->isStore() ) { 884 toRename->iewInfo[tid].dispatchedToLSQ++; 885 } 886 887 toRename->iewInfo[tid].dispatched++; 888 889 insts[tid].pop(); 890 } 891} 892 893template <class Impl> 894void 895DefaultIEW<Impl>::wakeCPU() 896{ 897 cpu->wakeCPU(); 898} 899 900template <class Impl> 901void 902DefaultIEW<Impl>::activityThisCycle() 903{ 904 DPRINTF(Activity, "Activity this cycle.\n"); 905 cpu->activityThisCycle(); 906} 907 908template <class Impl> 909inline void 910DefaultIEW<Impl>::activateStage() 911{ 912 DPRINTF(Activity, "Activating stage.\n"); 913 cpu->activateStage(O3CPU::IEWIdx); 914} 915 916template <class Impl> 917inline void 918DefaultIEW<Impl>::deactivateStage() 919{ 920 DPRINTF(Activity, "Deactivating stage.\n"); 921 cpu->deactivateStage(O3CPU::IEWIdx); 922} 923 924template<class Impl> 925void 926DefaultIEW<Impl>::dispatch(ThreadID tid) 927{ 928 // If status is Running or idle, 929 // call dispatchInsts() 930 // If status is Unblocking, 931 // buffer any instructions coming from rename 932 // continue trying to empty skid buffer 933 // check if stall conditions have passed 934 935 if (dispatchStatus[tid] == Blocked) { 936 ++iewBlockCycles; 937 938 } else if (dispatchStatus[tid] == Squashing) { 939 ++iewSquashCycles; 940 } 941 942 // Dispatch should try to dispatch as many instructions as its bandwidth 943 // will allow, as long as it is not currently blocked. 944 if (dispatchStatus[tid] == Running || 945 dispatchStatus[tid] == Idle) { 946 DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run " 947 "dispatch.\n", tid); 948 949 dispatchInsts(tid); 950 } else if (dispatchStatus[tid] == Unblocking) { 951 // Make sure that the skid buffer has something in it if the 952 // status is unblocking. 953 assert(!skidsEmpty()); 954 955 // If the status was unblocking, then instructions from the skid 956 // buffer were used. Remove those instructions and handle 957 // the rest of unblocking. 958 dispatchInsts(tid); 959 960 ++iewUnblockCycles; 961 962 if (validInstsFromRename()) { 963 // Add the current inputs to the skid buffer so they can be 964 // reprocessed when this stage unblocks. 965 skidInsert(tid); 966 } 967 968 unblock(tid); 969 } 970} 971 972template <class Impl> 973void 974DefaultIEW<Impl>::dispatchInsts(ThreadID tid) 975{ 976 // Obtain instructions from skid buffer if unblocking, or queue from rename 977 // otherwise. 978 std::queue<DynInstPtr> &insts_to_dispatch = 979 dispatchStatus[tid] == Unblocking ? 980 skidBuffer[tid] : insts[tid]; 981 982 int insts_to_add = insts_to_dispatch.size(); 983 984 DynInstPtr inst; 985 bool add_to_iq = false; 986 int dis_num_inst = 0; 987 988 // Loop through the instructions, putting them in the instruction 989 // queue. 990 for ( ; dis_num_inst < insts_to_add && 991 dis_num_inst < dispatchWidth; 992 ++dis_num_inst) 993 { 994 inst = insts_to_dispatch.front(); 995 996 if (dispatchStatus[tid] == Unblocking) { 997 DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid " 998 "buffer\n", tid); 999 } 1000 1001 // Make sure there's a valid instruction there. 1002 assert(inst); 1003 1004 DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %s [sn:%lli] [tid:%i] to " 1005 "IQ.\n", 1006 tid, inst->pcState(), inst->seqNum, inst->threadNumber); 1007 1008 // Be sure to mark these instructions as ready so that the 1009 // commit stage can go ahead and execute them, and mark 1010 // them as issued so the IQ doesn't reprocess them. 1011 1012 // Check for squashed instructions. 1013 if (inst->isSquashed()) { 1014 DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, " 1015 "not adding to IQ.\n", tid); 1016 1017 ++iewDispSquashedInsts; 1018 1019 insts_to_dispatch.pop(); 1020 1021 //Tell Rename That An Instruction has been processed 1022 if (inst->isLoad() || inst->isStore()) { 1023 toRename->iewInfo[tid].dispatchedToLSQ++; 1024 } 1025 toRename->iewInfo[tid].dispatched++; 1026 1027 continue; 1028 } 1029 1030 // Check for full conditions. 1031 if (instQueue.isFull(tid)) { 1032 DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid); 1033 1034 // Call function to start blocking. 1035 block(tid); 1036 1037 // Set unblock to false. Special case where we are using 1038 // skidbuffer (unblocking) instructions but then we still 1039 // get full in the IQ. 1040 toRename->iewUnblock[tid] = false; 1041 1042 ++iewIQFullEvents; 1043 break; 1044 } else if (ldstQueue.isFull(tid)) { 1045 DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid); 1046 1047 // Call function to start blocking. 1048 block(tid); 1049 1050 // Set unblock to false. Special case where we are using 1051 // skidbuffer (unblocking) instructions but then we still 1052 // get full in the IQ. 1053 toRename->iewUnblock[tid] = false; 1054 1055 ++iewLSQFullEvents; 1056 break; 1057 } 1058 1059 // Otherwise issue the instruction just fine. 1060 if (inst->isLoad()) { 1061 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1062 "encountered, adding to LSQ.\n", tid); 1063 1064 // Reserve a spot in the load store queue for this 1065 // memory access. 1066 ldstQueue.insertLoad(inst); 1067 1068 ++iewDispLoadInsts; 1069 1070 add_to_iq = true; 1071 1072 toRename->iewInfo[tid].dispatchedToLSQ++; 1073 } else if (inst->isStore()) { 1074 DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction " 1075 "encountered, adding to LSQ.\n", tid); 1076 1077 ldstQueue.insertStore(inst); 1078 1079 ++iewDispStoreInsts; 1080 1081 if (inst->isStoreConditional()) { 1082 // Store conditionals need to be set as "canCommit()" 1083 // so that commit can process them when they reach the 1084 // head of commit. 1085 // @todo: This is somewhat specific to Alpha. 1086 inst->setCanCommit(); 1087 instQueue.insertNonSpec(inst); 1088 add_to_iq = false; 1089 1090 ++iewDispNonSpecInsts; 1091 } else { 1092 add_to_iq = true; 1093 } 1094 1095 toRename->iewInfo[tid].dispatchedToLSQ++; 1096 } else if (inst->isMemBarrier() || inst->isWriteBarrier()) { 1097 // Same as non-speculative stores. 1098 inst->setCanCommit(); 1099 instQueue.insertBarrier(inst); 1100 add_to_iq = false; 1101 } else if (inst->isNop()) { 1102 DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, " 1103 "skipping.\n", tid); 1104 1105 inst->setIssued(); 1106 inst->setExecuted(); 1107 inst->setCanCommit(); 1108 1109 instQueue.recordProducer(inst); 1110 1111 iewExecutedNop[tid]++; 1112 1113 add_to_iq = false; 1114 } else if (inst->isExecuted()) { 1115 assert(0 && "Instruction shouldn't be executed.\n"); 1116 DPRINTF(IEW, "Issue: Executed branch encountered, " 1117 "skipping.\n"); 1118 1119 inst->setIssued(); 1120 inst->setCanCommit(); 1121 1122 instQueue.recordProducer(inst); 1123 1124 add_to_iq = false; 1125 } else { 1126 add_to_iq = true; 1127 } 1128 if (inst->isNonSpeculative()) { 1129 DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction " 1130 "encountered, skipping.\n", tid); 1131 1132 // Same as non-speculative stores. 1133 inst->setCanCommit(); 1134 1135 // Specifically insert it as nonspeculative. 1136 instQueue.insertNonSpec(inst); 1137 1138 ++iewDispNonSpecInsts; 1139 1140 add_to_iq = false; 1141 } 1142 1143 // If the instruction queue is not full, then add the 1144 // instruction. 1145 if (add_to_iq) { 1146 instQueue.insert(inst); 1147 } 1148 1149 insts_to_dispatch.pop(); 1150 1151 toRename->iewInfo[tid].dispatched++; 1152 1153 ++iewDispatchedInsts; 1154 1155#if TRACING_ON 1156 inst->dispatchTick = curTick() - inst->fetchTick; 1157#endif 1158 } 1159 1160 if (!insts_to_dispatch.empty()) { 1161 DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n", tid); 1162 block(tid); 1163 toRename->iewUnblock[tid] = false; 1164 } 1165 1166 if (dispatchStatus[tid] == Idle && dis_num_inst) { 1167 dispatchStatus[tid] = Running; 1168 1169 updatedQueues = true; 1170 } 1171 1172 dis_num_inst = 0; 1173} 1174 1175template <class Impl> 1176void 1177DefaultIEW<Impl>::printAvailableInsts() 1178{ 1179 int inst = 0; 1180 1181 std::cout << "Available Instructions: "; 1182 1183 while (fromIssue->insts[inst]) { 1184 1185 if (inst%3==0) std::cout << "\n\t"; 1186 1187 std::cout << "PC: " << fromIssue->insts[inst]->pcState() 1188 << " TN: " << fromIssue->insts[inst]->threadNumber 1189 << " SN: " << fromIssue->insts[inst]->seqNum << " | "; 1190 1191 inst++; 1192 1193 } 1194 1195 std::cout << "\n"; 1196} 1197 1198template <class Impl> 1199void 1200DefaultIEW<Impl>::executeInsts() 1201{ 1202 wbNumInst = 0; 1203 wbCycle = 0; 1204 1205 list<ThreadID>::iterator threads = activeThreads->begin(); 1206 list<ThreadID>::iterator end = activeThreads->end(); 1207 1208 while (threads != end) { 1209 ThreadID tid = *threads++; 1210 fetchRedirect[tid] = false; 1211 } 1212 1213 // Uncomment this if you want to see all available instructions. 1214 // @todo This doesn't actually work anymore, we should fix it. 1215// printAvailableInsts(); 1216 1217 // Execute/writeback any instructions that are available. 1218 int insts_to_execute = fromIssue->size; 1219 int inst_num = 0; 1220 for (; inst_num < insts_to_execute; 1221 ++inst_num) { 1222 1223 DPRINTF(IEW, "Execute: Executing instructions from IQ.\n"); 1224 1225 DynInstPtr inst = instQueue.getInstToExecute(); 1226 1227 DPRINTF(IEW, "Execute: Processing PC %s, [tid:%i] [sn:%i].\n", 1228 inst->pcState(), inst->threadNumber,inst->seqNum); 1229 1230 // Check if the instruction is squashed; if so then skip it 1231 if (inst->isSquashed()) { 1232 DPRINTF(IEW, "Execute: Instruction was squashed. PC: %s, [tid:%i]" 1233 " [sn:%i]\n", inst->pcState(), inst->threadNumber, 1234 inst->seqNum); 1235 1236 // Consider this instruction executed so that commit can go 1237 // ahead and retire the instruction. 1238 inst->setExecuted(); 1239 1240 // Not sure if I should set this here or just let commit try to 1241 // commit any squashed instructions. I like the latter a bit more. 1242 inst->setCanCommit(); 1243 1244 ++iewExecSquashedInsts; 1245 1246 decrWb(inst->seqNum); 1247 continue; 1248 } 1249 1250 Fault fault = NoFault; 1251 1252 // Execute instruction. 1253 // Note that if the instruction faults, it will be handled 1254 // at the commit stage. 1255 if (inst->isMemRef()) { 1256 DPRINTF(IEW, "Execute: Calculating address for memory " 1257 "reference.\n"); 1258 1259 // Tell the LDSTQ to execute this instruction (if it is a load). 1260 if (inst->isLoad()) { 1261 // Loads will mark themselves as executed, and their writeback 1262 // event adds the instruction to the queue to commit 1263 fault = ldstQueue.executeLoad(inst); 1264 1265 if (inst->isTranslationDelayed() && 1266 fault == NoFault) { 1267 // A hw page table walk is currently going on; the 1268 // instruction must be deferred. 1269 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1270 "load.\n"); 1271 instQueue.deferMemInst(inst); 1272 continue; 1273 } 1274 1275 if (inst->isDataPrefetch() || inst->isInstPrefetch()) { 1276 inst->fault = NoFault; 1277 } 1278 } else if (inst->isStore()) { 1279 fault = ldstQueue.executeStore(inst); 1280 1281 if (inst->isTranslationDelayed() && 1282 fault == NoFault) { 1283 // A hw page table walk is currently going on; the 1284 // instruction must be deferred. 1285 DPRINTF(IEW, "Execute: Delayed translation, deferring " 1286 "store.\n"); 1287 instQueue.deferMemInst(inst); 1288 continue; 1289 } 1290 1291 // If the store had a fault then it may not have a mem req 1292 if (fault != NoFault || inst->readPredicate() == false || 1293 !inst->isStoreConditional()) { 1294 // If the instruction faulted, then we need to send it along 1295 // to commit without the instruction completing. 1296 // Send this instruction to commit, also make sure iew stage 1297 // realizes there is activity. 1298 inst->setExecuted(); 1299 instToCommit(inst); 1300 activityThisCycle(); 1301 } 1302 1303 // Store conditionals will mark themselves as 1304 // executed, and their writeback event will add the 1305 // instruction to the queue to commit. 1306 } else { 1307 panic("Unexpected memory type!\n"); 1308 } 1309 1310 } else { 1311 // If the instruction has already faulted, then skip executing it. 1312 // Such case can happen when it faulted during ITLB translation. 1313 // If we execute the instruction (even if it's a nop) the fault 1314 // will be replaced and we will lose it. 1315 if (inst->getFault() == NoFault) { 1316 inst->execute(); 1317 if (inst->readPredicate() == false) 1318 inst->forwardOldRegs(); 1319 } 1320 1321 inst->setExecuted(); 1322 1323 instToCommit(inst); 1324 } 1325 1326 updateExeInstStats(inst); 1327 1328 // Check if branch prediction was correct, if not then we need 1329 // to tell commit to squash in flight instructions. Only 1330 // handle this if there hasn't already been something that 1331 // redirects fetch in this group of instructions. 1332 1333 // This probably needs to prioritize the redirects if a different 1334 // scheduler is used. Currently the scheduler schedules the oldest 1335 // instruction first, so the branch resolution order will be correct. 1336 ThreadID tid = inst->threadNumber; 1337 1338 if (!fetchRedirect[tid] || 1339 !toCommit->squash[tid] || 1340 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1341 1342 // Prevent testing for misprediction on load instructions, 1343 // that have not been executed. 1344 bool loadNotExecuted = !inst->isExecuted() && inst->isLoad(); 1345 1346 if (inst->mispredicted() && !loadNotExecuted) { 1347 fetchRedirect[tid] = true; 1348 1349 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1350 DPRINTF(IEW, "Predicted target was PC: %s.\n", 1351 inst->readPredTarg()); 1352 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %s.\n", 1353 inst->pcState()); 1354 // If incorrect, then signal the ROB that it must be squashed. 1355 squashDueToBranch(inst, tid); 1356 1357 if (inst->readPredTaken()) { 1358 predictedTakenIncorrect++; 1359 } else { 1360 predictedNotTakenIncorrect++; 1361 } 1362 } else if (ldstQueue.violation(tid)) { 1363 assert(inst->isMemRef()); 1364 // If there was an ordering violation, then get the 1365 // DynInst that caused the violation. Note that this 1366 // clears the violation signal. 1367 DynInstPtr violator; 1368 violator = ldstQueue.getMemDepViolator(tid); 1369 1370 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: %s " 1371 "[sn:%lli], inst PC: %s [sn:%lli]. Addr is: %#x.\n", 1372 violator->pcState(), violator->seqNum, 1373 inst->pcState(), inst->seqNum, inst->physEffAddr); 1374 1375 fetchRedirect[tid] = true; 1376 1377 // Tell the instruction queue that a violation has occured. 1378 instQueue.violation(inst, violator); 1379 1380 // Squash. 1381 squashDueToMemOrder(violator, tid); 1382 1383 ++memOrderViolationEvents; 1384 } else if (ldstQueue.loadBlocked(tid) && 1385 !ldstQueue.isLoadBlockedHandled(tid)) { 1386 fetchRedirect[tid] = true; 1387 1388 DPRINTF(IEW, "Load operation couldn't execute because the " 1389 "memory system is blocked. PC: %s [sn:%lli]\n", 1390 inst->pcState(), inst->seqNum); 1391 1392 squashDueToMemBlocked(inst, tid); 1393 } 1394 } else { 1395 // Reset any state associated with redirects that will not 1396 // be used. 1397 if (ldstQueue.violation(tid)) { 1398 assert(inst->isMemRef()); 1399 1400 DynInstPtr violator = ldstQueue.getMemDepViolator(tid); 1401 1402 DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: " 1403 "%s, inst PC: %s. Addr is: %#x.\n", 1404 violator->pcState(), inst->pcState(), 1405 inst->physEffAddr); 1406 DPRINTF(IEW, "Violation will not be handled because " 1407 "already squashing\n"); 1408 1409 ++memOrderViolationEvents; 1410 } 1411 if (ldstQueue.loadBlocked(tid) && 1412 !ldstQueue.isLoadBlockedHandled(tid)) { 1413 DPRINTF(IEW, "Load operation couldn't execute because the " 1414 "memory system is blocked. PC: %s [sn:%lli]\n", 1415 inst->pcState(), inst->seqNum); 1416 DPRINTF(IEW, "Blocked load will not be handled because " 1417 "already squashing\n"); 1418 1419 ldstQueue.setLoadBlockedHandled(tid); 1420 } 1421 1422 } 1423 } 1424 1425 // Update and record activity if we processed any instructions. 1426 if (inst_num) { 1427 if (exeStatus == Idle) { 1428 exeStatus = Running; 1429 } 1430 1431 updatedQueues = true; 1432 1433 cpu->activityThisCycle(); 1434 } 1435 1436 // Need to reset this in case a writeback event needs to write into the 1437 // iew queue. That way the writeback event will write into the correct 1438 // spot in the queue. 1439 wbNumInst = 0; 1440 1441} 1442 1443template <class Impl> 1444void 1445DefaultIEW<Impl>::writebackInsts() 1446{ 1447 // Loop through the head of the time buffer and wake any 1448 // dependents. These instructions are about to write back. Also 1449 // mark scoreboard that this instruction is finally complete. 1450 // Either have IEW have direct access to scoreboard, or have this 1451 // as part of backwards communication. 1452 for (int inst_num = 0; inst_num < wbWidth && 1453 toCommit->insts[inst_num]; inst_num++) { 1454 DynInstPtr inst = toCommit->insts[inst_num]; 1455 ThreadID tid = inst->threadNumber; 1456 1457 DPRINTF(IEW, "Sending instructions to commit, [sn:%lli] PC %s.\n", 1458 inst->seqNum, inst->pcState()); 1459 1460 iewInstsToCommit[tid]++; 1461 1462 // Some instructions will be sent to commit without having 1463 // executed because they need commit to handle them. 1464 // E.g. Uncached loads have not actually executed when they 1465 // are first sent to commit. Instead commit must tell the LSQ 1466 // when it's ready to execute the uncached load. 1467 if (!inst->isSquashed() && inst->isExecuted() && inst->getFault() == NoFault) { 1468 int dependents = instQueue.wakeDependents(inst); 1469 1470 for (int i = 0; i < inst->numDestRegs(); i++) { 1471 //mark as Ready 1472 DPRINTF(IEW,"Setting Destination Register %i\n", 1473 inst->renamedDestRegIdx(i)); 1474 scoreboard->setReg(inst->renamedDestRegIdx(i)); 1475 } 1476 1477 if (dependents) { 1478 producerInst[tid]++; 1479 consumerInst[tid]+= dependents; 1480 } 1481 writebackCount[tid]++; 1482 } 1483 1484 decrWb(inst->seqNum); 1485 } 1486} 1487 1488template<class Impl> 1489void 1490DefaultIEW<Impl>::tick() 1491{ 1492 wbNumInst = 0; 1493 wbCycle = 0; 1494 1495 wroteToTimeBuffer = false; 1496 updatedQueues = false; 1497 1498 sortInsts(); 1499 1500 // Free function units marked as being freed this cycle. 1501 fuPool->processFreeUnits(); 1502 1503 list<ThreadID>::iterator threads = activeThreads->begin(); 1504 list<ThreadID>::iterator end = activeThreads->end(); 1505 1506 // Check stall and squash signals, dispatch any instructions. 1507 while (threads != end) { 1508 ThreadID tid = *threads++; 1509 1510 DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid); 1511 1512 checkSignalsAndUpdate(tid); 1513 dispatch(tid); 1514 } 1515 1516 if (exeStatus != Squashing) { 1517 executeInsts(); 1518 1519 writebackInsts(); 1520 1521 // Have the instruction queue try to schedule any ready instructions. 1522 // (In actuality, this scheduling is for instructions that will 1523 // be executed next cycle.) 1524 instQueue.scheduleReadyInsts(); 1525 1526 // Also should advance its own time buffers if the stage ran. 1527 // Not the best place for it, but this works (hopefully). 1528 issueToExecQueue.advance(); 1529 } 1530 1531 bool broadcast_free_entries = false; 1532 1533 if (updatedQueues || exeStatus == Running || updateLSQNextCycle) { 1534 exeStatus = Idle; 1535 updateLSQNextCycle = false; 1536 1537 broadcast_free_entries = true; 1538 } 1539 1540 // Writeback any stores using any leftover bandwidth. 1541 ldstQueue.writebackStores(); 1542 1543 // Check the committed load/store signals to see if there's a load 1544 // or store to commit. Also check if it's being told to execute a 1545 // nonspeculative instruction. 1546 // This is pretty inefficient... 1547 1548 threads = activeThreads->begin(); 1549 while (threads != end) { 1550 ThreadID tid = (*threads++); 1551 1552 DPRINTF(IEW,"Processing [tid:%i]\n",tid); 1553 1554 // Update structures based on instructions committed. 1555 if (fromCommit->commitInfo[tid].doneSeqNum != 0 && 1556 !fromCommit->commitInfo[tid].squash && 1557 !fromCommit->commitInfo[tid].robSquashing) { 1558 1559 ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid); 1560 1561 ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid); 1562 1563 updateLSQNextCycle = true; 1564 instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid); 1565 } 1566 1567 if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) { 1568 1569 //DPRINTF(IEW,"NonspecInst from thread %i",tid); 1570 if (fromCommit->commitInfo[tid].uncached) { 1571 instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad); 1572 fromCommit->commitInfo[tid].uncachedLoad->setAtCommit(); 1573 } else { 1574 instQueue.scheduleNonSpec( 1575 fromCommit->commitInfo[tid].nonSpecSeqNum); 1576 } 1577 } 1578 1579 if (broadcast_free_entries) { 1580 toFetch->iewInfo[tid].iqCount = 1581 instQueue.getCount(tid); 1582 toFetch->iewInfo[tid].ldstqCount = 1583 ldstQueue.getCount(tid); 1584 1585 toRename->iewInfo[tid].usedIQ = true; 1586 toRename->iewInfo[tid].freeIQEntries = 1587 instQueue.numFreeEntries(); 1588 toRename->iewInfo[tid].usedLSQ = true; 1589 toRename->iewInfo[tid].freeLSQEntries = 1590 ldstQueue.numFreeEntries(tid); 1591 1592 wroteToTimeBuffer = true; 1593 } 1594 1595 DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n", 1596 tid, toRename->iewInfo[tid].dispatched); 1597 } 1598 1599 DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). " 1600 "LSQ has %i free entries.\n", 1601 instQueue.numFreeEntries(), instQueue.hasReadyInsts(), 1602 ldstQueue.numFreeEntries()); 1603 1604 updateStatus(); 1605 1606 if (wroteToTimeBuffer) { 1607 DPRINTF(Activity, "Activity this cycle.\n"); 1608 cpu->activityThisCycle(); 1609 } 1610} 1611 1612template <class Impl> 1613void 1614DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst) 1615{ 1616 ThreadID tid = inst->threadNumber; 1617 1618 iewExecutedInsts++; 1619 1620#if TRACING_ON 1621 if (DTRACE(O3PipeView)) { 1622 inst->completeTick = curTick() - inst->fetchTick; 1623 } 1624#endif 1625 1626 // 1627 // Control operations 1628 // 1629 if (inst->isControl()) 1630 iewExecutedBranches[tid]++; 1631 1632 // 1633 // Memory operations 1634 // 1635 if (inst->isMemRef()) { 1636 iewExecutedRefs[tid]++; 1637 1638 if (inst->isLoad()) { 1639 iewExecLoadInsts[tid]++; 1640 } 1641 } 1642} 1643 1644template <class Impl> 1645void 1646DefaultIEW<Impl>::checkMisprediction(DynInstPtr &inst) 1647{ 1648 ThreadID tid = inst->threadNumber; 1649 1650 if (!fetchRedirect[tid] || 1651 !toCommit->squash[tid] || 1652 toCommit->squashedSeqNum[tid] > inst->seqNum) { 1653 1654 if (inst->mispredicted()) { 1655 fetchRedirect[tid] = true; 1656 1657 DPRINTF(IEW, "Execute: Branch mispredict detected.\n"); 1658 DPRINTF(IEW, "Predicted target was PC:%#x, NPC:%#x.\n", 1659 inst->predInstAddr(), inst->predNextInstAddr()); 1660 DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x," 1661 " NPC: %#x.\n", inst->nextInstAddr(), 1662 inst->nextInstAddr()); 1663 // If incorrect, then signal the ROB that it must be squashed. 1664 squashDueToBranch(inst, tid); 1665 1666 if (inst->readPredTaken()) { 1667 predictedTakenIncorrect++; 1668 } else { 1669 predictedNotTakenIncorrect++; 1670 } 1671 } 1672 } 1673} 1674