iew_impl.hh

来自「linux下基于c++的处理器仿真平台。具有处理器流水线」· HH 代码 · 共 740 行 · 第 1/2 页

HH
740
字号
/* * Copyright (c) 2004, 2005 * The Regents of The University of Michigan * All Rights Reserved * * This code is part of the M5 simulator, developed by Nathan Binkert, * Erik Hallnor, Steve Raasch, and Steve Reinhardt, with contributions * from Ron Dreslinski, Dave Greene, Lisa Hsu, Kevin Lim, Ali Saidi,  * and Andrew Schultz. * * Permission is granted to use, copy, create derivative works and * redistribute this software and such derivative works for any * purpose, so long as the copyright notice above, this grant of * permission, and the disclaimer below appear in all copies made; and * so long as the name of The University of Michigan is not used in * any advertising or publicity pertaining to the use or distribution * of this software without specific, written prior authorization. * * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION FROM THE * UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY PURPOSE, AND * WITHOUT WARRANTY BY THE UNIVERSITY OF MICHIGAN OF ANY KIND, EITHER * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE. THE REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE * LIABLE FOR ANY DAMAGES, INCLUDING DIRECT, SPECIAL, INDIRECT, * INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM * ARISING OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF SUCH * DAMAGES. */// @todo: Fix the instantaneous communication among all the stages within// iew.  There's a clear delay between issue and execute, yet backwards// communication happens simultaneously.// Update the statuses for each stage.#include <queue>#include "base/timebuf.hh"#include "cpu/o3/iew.hh"template<class Impl>SimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,                                                SimpleIEW<Impl> *_iew)    : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew){    this->setFlags(Event::AutoDelete);}template<class Impl>voidSimpleIEW<Impl>::WritebackEvent::process(){    DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");    // Need to insert instruction into queue to commit    iewStage->instToCommit(inst);    // Need to execute second half of the instruction, do actual writing to    // registers and such    inst->execute();}template<class Impl>const char *SimpleIEW<Impl>::WritebackEvent::description(){    return "LSQ writeback event";}template<class Impl>SimpleIEW<Impl>::SimpleIEW(Params &params)    : // Just make this time buffer really big for now      issueToExecQueue(5, 5),      instQueue(params),      ldstQueue(params),      commitToIEWDelay(params.commitToIEWDelay),      renameToIEWDelay(params.renameToIEWDelay),      issueToExecuteDelay(params.issueToExecuteDelay),      issueReadWidth(params.issueWidth),      issueWidth(params.issueWidth),      executeWidth(params.executeWidth){    DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);    _status = Idle;    _issueStatus = Idle;    _exeStatus = Idle;    _wbStatus = Idle;    // Setup wire to read instructions coming from issue.    fromIssue = issueToExecQueue.getWire(-issueToExecuteDelay);        // Instruction queue needs the queue between issue and execute.    instQueue.setIssueToExecuteQueue(&issueToExecQueue);    ldstQueue.setIEW(this);}template <class Impl>voidSimpleIEW<Impl>::regStats(){    instQueue.regStats();    iewIdleCycles        .name(name() + ".iewIdleCycles")        .desc("Number of cycles IEW is idle");    iewSquashCycles        .name(name() + ".iewSquashCycles")        .desc("Number of cycles IEW is squashing");    iewBlockCycles        .name(name() + ".iewBlockCycles")        .desc("Number of cycles IEW is blocking");    iewUnblockCycles        .name(name() + ".iewUnblockCycles")        .desc("Number of cycles IEW is unblocking");//    iewWBInsts;    iewDispatchedInsts        .name(name() + ".iewDispatchedInsts")        .desc("Number of instructions dispatched to IQ");    iewDispSquashedInsts        .name(name() + ".iewDispSquashedInsts")        .desc("Number of squashed instructions skipped by dispatch");    iewDispLoadInsts        .name(name() + ".iewDispLoadInsts")        .desc("Number of dispatched load instructions");    iewDispStoreInsts        .name(name() + ".iewDispStoreInsts")        .desc("Number of dispatched store instructions");    iewDispNonSpecInsts        .name(name() + ".iewDispNonSpecInsts")        .desc("Number of dispatched non-speculative instructions");    iewIQFullEvents        .name(name() + ".iewIQFullEvents")        .desc("Number of times the IQ has become full, causing a stall");    iewExecutedInsts        .name(name() + ".iewExecutedInsts")        .desc("Number of executed instructions");    iewExecLoadInsts        .name(name() + ".iewExecLoadInsts")        .desc("Number of load instructions executed");    iewExecStoreInsts        .name(name() + ".iewExecStoreInsts")        .desc("Number of store instructions executed");    iewExecSquashedInsts        .name(name() + ".iewExecSquashedInsts")        .desc("Number of squashed instructions skipped in execute");    memOrderViolationEvents        .name(name() + ".memOrderViolationEvents")        .desc("Number of memory order violations");    predictedTakenIncorrect        .name(name() + ".predictedTakenIncorrect")        .desc("Number of branches that were predicted taken incorrectly");}template<class Impl>voidSimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr){    DPRINTF(IEW, "IEW: Setting CPU pointer.\n");    cpu = cpu_ptr;    instQueue.setCPU(cpu_ptr);    ldstQueue.setCPU(cpu_ptr);}template<class Impl>voidSimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr){    DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");    timeBuffer = tb_ptr;    // Setup wire to read information from time buffer, from commit.    fromCommit = timeBuffer->getWire(-commitToIEWDelay);    // Setup wire to write information back to previous stages.    toRename = timeBuffer->getWire(0);    // Instruction queue also needs main time buffer.    instQueue.setTimeBuffer(tb_ptr);}template<class Impl>voidSimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr){    DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");    renameQueue = rq_ptr;    // Setup wire to read information from rename queue.    fromRename = renameQueue->getWire(-renameToIEWDelay);}template<class Impl>voidSimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr){    DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");    iewQueue = iq_ptr;    // Setup wire to write instructions to commit.    toCommit = iewQueue->getWire(0);}template<class Impl>voidSimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr){    DPRINTF(IEW, "IEW: Setting rename map pointer.\n");    renameMap = rm_ptr;}template<class Impl>voidSimpleIEW<Impl>::squash(){    DPRINTF(IEW, "IEW: Squashing all instructions.\n");    _status = Squashing;    // Tell the IQ to start squashing.    instQueue.squash();    // Tell the LDSTQ to start squashing.    ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);}template<class Impl>voidSimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst){    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",            inst->PC);    // Perhaps leave the squashing up to the ROB stage to tell it when to    // squash?    _status = Squashing;    // Tell rename to squash through the time buffer.    toCommit->squash = true;    // Also send PC update information back to prior stages.    toCommit->squashedSeqNum = inst->seqNum;    toCommit->mispredPC = inst->readPC();    toCommit->nextPC = inst->readNextPC();    toCommit->branchMispredict = true;    // Prediction was incorrect, so send back inverse.    toCommit->branchTaken = inst->readNextPC() !=         (inst->readPC() + sizeof(MachInst));}template<class Impl>voidSimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst){    DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",            inst->PC);    // Perhaps leave the squashing up to the ROB stage to tell it when to    // squash?    _status = Squashing;    // Tell rename to squash through the time buffer.    toCommit->squash = true;    // Also send PC update information back to prior stages.    toCommit->squashedSeqNum = inst->seqNum;    toCommit->nextPC = inst->readNextPC();}template<class Impl>voidSimpleIEW<Impl>::block(){    DPRINTF(IEW, "IEW: Blocking.\n");    // Set the status to Blocked.    _status = Blocked;    // Add the current inputs to the skid buffer so they can be     // reprocessed when this stage unblocks.    skidBuffer.push(*fromRename);        // Note that this stage only signals previous stages to stall when    // it is the cause of the stall originates at this stage.  Otherwise    // the previous stages are expected to check all possible stall signals.}template<class Impl>inline voidSimpleIEW<Impl>::unblock(){    // Check if there's information in the skid buffer.  If there is, then    // set status to unblocking, otherwise set it directly to running.    DPRINTF(IEW, "IEW: Reading instructions out of the skid "            "buffer.\n");    // Remove the now processed instructions from the skid buffer.    skidBuffer.pop();        // If there's still information in the skid buffer, then     // continue to tell previous stages to stall.  They will be     // able to restart once the skid buffer is empty.       if (!skidBuffer.empty()) {        toRename->iewInfo.stall = true;    } else {        DPRINTF(IEW, "IEW: Stage is done unblocking.\n");        _status = Running;    }}template<class Impl>voidSimpleIEW<Impl>::wakeDependents(DynInstPtr &inst){    instQueue.wakeDependents(inst);}template<class Impl>voidSimpleIEW<Impl>::instToCommit(DynInstPtr &inst){    }template <class Impl>voidSimpleIEW<Impl>::dispatchInsts(){    ////////////////////////////////////////    // DISPATCH/ISSUE stage    ////////////////////////////////////////    //Put into its own function?    //Add instructions to IQ if there are any instructions there    // Check if there are any instructions coming from rename, and we're.    // not squashing.    if (fromRename->size > 0) {        int insts_to_add = fromRename->size;        // Loop through the instructions, putting them in the instruction        // queue.        for (int inst_num = 0; inst_num < insts_to_add; ++inst_num)        {            DynInstPtr inst = fromRename->insts[inst_num];            // Make sure there's a valid instruction there.            assert(inst);            DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",                     inst->readPC());            // Be sure to mark these instructions as ready so that the            // commit stage can go ahead and execute them, and mark            // them as issued so the IQ doesn't reprocess them.            if (inst->isSquashed()) {                ++iewDispSquashedInsts;                continue;            } else if (instQueue.isFull()) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?