2c2
< * Copyright (c) 2004-2006 The Regents of The University of Michigan
---
> * Copyright (c) 2004-2005 The Regents of The University of Michigan
26a27,28
> *
> * Authors: Kevin Lim
31a34
> // Update the statuses for each stage.
36d38
< #include "cpu/o3/fu_pool.hh"
39,40d40
< using namespace std;
<
42,44c42,44
< DefaultIEW<Impl>::LdWritebackEvent::LdWritebackEvent(DynInstPtr &_inst,
< DefaultIEW<Impl> *_iew)
< : Event(&mainEventQueue), inst(_inst), iewStage(_iew)
---
> SimpleIEW<Impl>::WritebackEvent::WritebackEvent(DynInstPtr &_inst,
> SimpleIEW<Impl> *_iew)
> : Event(&mainEventQueue, CPU_Tick_Pri), inst(_inst), iewStage(_iew)
51c51
< DefaultIEW<Impl>::LdWritebackEvent::process()
---
> SimpleIEW<Impl>::WritebackEvent::process()
53,54c53
< DPRINTF(IEW, "Load writeback event [sn:%lli]\n", inst->seqNum);
< DPRINTF(Activity, "Activity: Ld Writeback event [sn:%lli]\n", inst->seqNum);
---
> DPRINTF(IEW, "IEW: WRITEBACK EVENT!!!!\n");
56,77d54
< //iewStage->ldstQueue.removeMSHR(inst->threadNumber,inst->seqNum);
<
< if (iewStage->isSwitchedOut()) {
< inst = NULL;
< return;
< } else if (inst->isSquashed()) {
< iewStage->wakeCPU();
< inst = NULL;
< return;
< }
<
< iewStage->wakeCPU();
<
< if (!inst->isExecuted()) {
< inst->setExecuted();
<
< // Complete access to copy data to proper place.
< if (inst->isStore()) {
< inst->completeAcc();
< }
< }
<
80,83c57,59
<
< iewStage->activityThisCycle();
<
< inst = NULL;
---
> // Need to execute second half of the instruction, do actual writing to
> // registers and such
> inst->execute();
88c64
< DefaultIEW<Impl>::LdWritebackEvent::description()
---
> SimpleIEW<Impl>::WritebackEvent::description()
90c66
< return "Load writeback event";
---
> return "LSQ writeback event";
94,95c70,71
< DefaultIEW<Impl>::DefaultIEW(Params *params)
< : // @todo: Make this into a parameter.
---
> SimpleIEW<Impl>::SimpleIEW(Params &params)
> : // Just make this time buffer really big for now
99,107c75,80
< fuPool(params->fuPool),
< commitToIEWDelay(params->commitToIEWDelay),
< renameToIEWDelay(params->renameToIEWDelay),
< issueToExecuteDelay(params->issueToExecuteDelay),
< issueReadWidth(params->issueWidth),
< issueWidth(params->issueWidth),
< executeWidth(params->executeWidth),
< numThreads(params->numberOfThreads),
< switchedOut(false)
---
> commitToIEWDelay(params.commitToIEWDelay),
> renameToIEWDelay(params.renameToIEWDelay),
> issueToExecuteDelay(params.issueToExecuteDelay),
> issueReadWidth(params.issueWidth),
> issueWidth(params.issueWidth),
> executeWidth(params.executeWidth)
109,111c82,86
< _status = Active;
< exeStatus = Running;
< wbStatus = Idle;
---
> DPRINTF(IEW, "IEW: executeIntWidth: %i.\n", params.executeIntWidth);
> _status = Idle;
> _issueStatus = Idle;
> _exeStatus = Idle;
> _wbStatus = Idle;
119d93
< instQueue.setIEW(this);
121,130d94
<
< for (int i=0; i < numThreads; i++) {
< dispatchStatus[i] = Running;
< stalls[i].commit = false;
< fetchRedirect[i] = false;
< }
<
< updateLSQNextCycle = false;
<
< skidBufferMax = (3 * (renameToIEWDelay * params->renameWidth)) + issueWidth;
134,140d97
< std::string
< DefaultIEW<Impl>::name() const
< {
< return cpu->name() + ".iew";
< }
<
< template <class Impl>
142c99
< DefaultIEW<Impl>::regStats()
---
> SimpleIEW<Impl>::regStats()
144,145d100
< using namespace Stats;
<
163a119,120
> // iewWBInsts;
>
188,191d144
< iewLSQFullEvents
< .name(name() + ".iewLSQFullEvents")
< .desc("Number of times the LSQ has become full, causing a stall");
<
197d149
< .init(cpu->number_of_threads)
199,200c151
< .desc("Number of load instructions executed")
< .flags(total);
---
> .desc("Number of load instructions executed");
201a153,156
> iewExecStoreInsts
> .name(name() + ".iewExecStoreInsts")
> .desc("Number of store instructions executed");
>
213,332d167
<
< predictedNotTakenIncorrect
< .name(name() + ".predictedNotTakenIncorrect")
< .desc("Number of branches that were predicted not taken incorrectly");
<
< branchMispredicts
< .name(name() + ".branchMispredicts")
< .desc("Number of branch mispredicts detected at execute");
<
< branchMispredicts = predictedTakenIncorrect + predictedNotTakenIncorrect;
<
< exeSwp
< .init(cpu->number_of_threads)
< .name(name() + ".EXEC:swp")
< .desc("number of swp insts executed")
< .flags(total)
< ;
<
< exeNop
< .init(cpu->number_of_threads)
< .name(name() + ".EXEC:nop")
< .desc("number of nop insts executed")
< .flags(total)
< ;
<
< exeRefs
< .init(cpu->number_of_threads)
< .name(name() + ".EXEC:refs")
< .desc("number of memory reference insts executed")
< .flags(total)
< ;
<
< exeBranches
< .init(cpu->number_of_threads)
< .name(name() + ".EXEC:branches")
< .desc("Number of branches executed")
< .flags(total)
< ;
<
< issueRate
< .name(name() + ".EXEC:rate")
< .desc("Inst execution rate")
< .flags(total)
< ;
< issueRate = iewExecutedInsts / cpu->numCycles;
<
< iewExecStoreInsts
< .name(name() + ".EXEC:stores")
< .desc("Number of stores executed")
< .flags(total)
< ;
< iewExecStoreInsts = exeRefs - iewExecLoadInsts;
< /*
< for (int i=0; i<Num_OpClasses; ++i) {
< stringstream subname;
< subname << opClassStrings[i] << "_delay";
< issue_delay_dist.subname(i, subname.str());
< }
< */
< //
< // Other stats
< //
<
< iewInstsToCommit
< .init(cpu->number_of_threads)
< .name(name() + ".WB:sent")
< .desc("cumulative count of insts sent to commit")
< .flags(total)
< ;
<
< writebackCount
< .init(cpu->number_of_threads)
< .name(name() + ".WB:count")
< .desc("cumulative count of insts written-back")
< .flags(total)
< ;
<
< producerInst
< .init(cpu->number_of_threads)
< .name(name() + ".WB:producers")
< .desc("num instructions producing a value")
< .flags(total)
< ;
<
< consumerInst
< .init(cpu->number_of_threads)
< .name(name() + ".WB:consumers")
< .desc("num instructions consuming a value")
< .flags(total)
< ;
<
< wbPenalized
< .init(cpu->number_of_threads)
< .name(name() + ".WB:penalized")
< .desc("number of instrctions required to write to 'other' IQ")
< .flags(total)
< ;
<
< wbPenalizedRate
< .name(name() + ".WB:penalized_rate")
< .desc ("fraction of instructions written-back that wrote to 'other' IQ")
< .flags(total)
< ;
<
< wbPenalizedRate = wbPenalized / writebackCount;
<
< wbFanout
< .name(name() + ".WB:fanout")
< .desc("average fanout of values written-back")
< .flags(total)
< ;
<
< wbFanout = producerInst / consumerInst;
<
< wbRate
< .name(name() + ".WB:rate")
< .desc("insts written-back per cycle")
< .flags(total)
< ;
< wbRate = writebackCount / cpu->numCycles;
337c172
< DefaultIEW<Impl>::initStage()
---
> SimpleIEW<Impl>::setCPU(FullCPU *cpu_ptr)
339,354c174
< for (int tid=0; tid < numThreads; tid++) {
< toRename->iewInfo[tid].usedIQ = true;
< toRename->iewInfo[tid].freeIQEntries =
< instQueue.numFreeEntries(tid);
<
< toRename->iewInfo[tid].usedLSQ = true;
< toRename->iewInfo[tid].freeLSQEntries =
< ldstQueue.numFreeEntries(tid);
< }
< }
<
< template<class Impl>
< void
< DefaultIEW<Impl>::setCPU(FullCPU *cpu_ptr)
< {
< DPRINTF(IEW, "Setting CPU pointer.\n");
---
> DPRINTF(IEW, "IEW: Setting CPU pointer.\n");
359,360d178
<
< cpu->activateStage(FullCPU::IEWIdx);
365c183
< DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
---
> SimpleIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
367c185
< DPRINTF(IEW, "Setting time buffer pointer.\n");
---
> DPRINTF(IEW, "IEW: Setting time buffer pointer.\n");
376,377d193
< toFetch = timeBuffer->getWire(0);
<
384c200
< DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
---
> SimpleIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
386c202
< DPRINTF(IEW, "Setting rename queue pointer.\n");
---
> DPRINTF(IEW, "IEW: Setting rename queue pointer.\n");
395c211
< DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
---
> SimpleIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
397c213
< DPRINTF(IEW, "Setting IEW queue pointer.\n");
---
> DPRINTF(IEW, "IEW: Setting IEW queue pointer.\n");
406c222
< DefaultIEW<Impl>::setActiveThreads(list<unsigned> *at_ptr)
---
> SimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
408,412c224,225
< DPRINTF(IEW, "Setting active threads list pointer.\n");
< activeThreads = at_ptr;
<
< ldstQueue.setActiveThreads(at_ptr);
< instQueue.setActiveThreads(at_ptr);
---
> DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
> renameMap = rm_ptr;
417c230
< DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
---
> SimpleIEW<Impl>::squash()
419,421c232,233
< DPRINTF(IEW, "Setting scoreboard pointer.\n");
< scoreboard = sb_ptr;
< }
---
> DPRINTF(IEW, "IEW: Squashing all instructions.\n");
> _status = Squashing;
423,493d234
< #if 0
< template<class Impl>
< void
< DefaultIEW<Impl>::setPageTable(PageTable *pt_ptr)
< {
< ldstQueue.setPageTable(pt_ptr);
< }
< #endif
<
< template <class Impl>
< void
< DefaultIEW<Impl>::switchOut()
< {
< cpu->signalSwitched();
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::doSwitchOut()
< {
< switchedOut = true;
<
< instQueue.switchOut();
< ldstQueue.switchOut();
< fuPool->switchOut();
<
< for (int i = 0; i < numThreads; i++) {
< while (!insts[i].empty())
< insts[i].pop();
< while (!skidBuffer[i].empty())
< skidBuffer[i].pop();
< }
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::takeOverFrom()
< {
< _status = Active;
< exeStatus = Running;
< wbStatus = Idle;
< switchedOut = false;
<
< instQueue.takeOverFrom();
< ldstQueue.takeOverFrom();
< fuPool->takeOverFrom();
<
< initStage();
< cpu->activityThisCycle();
<
< for (int i=0; i < numThreads; i++) {
< dispatchStatus[i] = Running;
< stalls[i].commit = false;
< fetchRedirect[i] = false;
< }
<
< updateLSQNextCycle = false;
<
< // @todo: Fix hardcoded number
< for (int i = 0; i < 6; ++i) {
< issueToExecQueue.advance();
< }
< }
<
< template<class Impl>
< void
< DefaultIEW<Impl>::squash(unsigned tid)
< {
< DPRINTF(IEW, "[tid:%i]: Squashing all instructions.\n",
< tid);
<
495c236
< instQueue.squash(tid);
---
> instQueue.squash();
498,524c239
< ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
<
< updatedQueues = true;
<
< // Clear the skid buffer in case it has any data in it.
< while (!skidBuffer[tid].empty()) {
<
< if (skidBuffer[tid].front()->isLoad() ||
< skidBuffer[tid].front()->isStore() ) {
< toRename->iewInfo[tid].dispatchedToLSQ++;
< }
<
< toRename->iewInfo[tid].dispatched++;
<
< skidBuffer[tid].pop();
< }
<
< while (!insts[tid].empty()) {
< if (insts[tid].front()->isLoad() ||
< insts[tid].front()->isStore() ) {
< toRename->iewInfo[tid].dispatchedToLSQ++;
< }
<
< toRename->iewInfo[tid].dispatched++;
<
< insts[tid].pop();
< }
---
> ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
529c244
< DefaultIEW<Impl>::squashDueToBranch(DynInstPtr &inst, unsigned tid)
---
> SimpleIEW<Impl>::squashDueToBranch(DynInstPtr &inst)
531,532c246,250
< DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, PC: %#x "
< "[sn:%i].\n", tid, inst->readPC(), inst->seqNum);
---
> 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;
534,539c252,260
< toCommit->squash[tid] = true;
< toCommit->squashedSeqNum[tid] = inst->seqNum;
< toCommit->mispredPC[tid] = inst->readPC();
< toCommit->nextPC[tid] = inst->readNextPC();
< toCommit->branchMispredict[tid] = true;
< toCommit->branchTaken[tid] = inst->readNextPC() !=
---
> // 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() !=
541,544d261
<
< toCommit->includeSquashInst[tid] = false;
<
< wroteToTimeBuffer = true;
549c266
< DefaultIEW<Impl>::squashDueToMemOrder(DynInstPtr &inst, unsigned tid)
---
> SimpleIEW<Impl>::squashDueToMem(DynInstPtr &inst)
551,552c268,272
< DPRINTF(IEW, "[tid:%i]: Squashing from a specific instruction, "
< "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
---
> 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;
554,560c274,278
< toCommit->squash[tid] = true;
< toCommit->squashedSeqNum[tid] = inst->seqNum;
< toCommit->nextPC[tid] = inst->readNextPC();
<
< toCommit->includeSquashInst[tid] = false;
<
< wroteToTimeBuffer = true;
---
> // 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();
565c283
< DefaultIEW<Impl>::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid)
---
> SimpleIEW<Impl>::block()
567,568c285,287
< DPRINTF(IEW, "[tid:%i]: Memory blocked, squashing load and younger insts, "
< "PC: %#x [sn:%i].\n", tid, inst->readPC(), inst->seqNum);
---
> DPRINTF(IEW, "IEW: Blocking.\n");
> // Set the status to Blocked.
> _status = Blocked;
570,592d288
< toCommit->squash[tid] = true;
< toCommit->squashedSeqNum[tid] = inst->seqNum;
< toCommit->nextPC[tid] = inst->readPC();
<
< toCommit->includeSquashInst[tid] = true;
<
< ldstQueue.setLoadBlockedHandled(tid);
<
< wroteToTimeBuffer = true;
< }
<
< template<class Impl>
< void
< DefaultIEW<Impl>::block(unsigned tid)
< {
< DPRINTF(IEW, "[tid:%u]: Blocking.\n", tid);
<
< if (dispatchStatus[tid] != Blocked &&
< dispatchStatus[tid] != Unblocking) {
< toRename->iewBlock[tid] = true;
< wroteToTimeBuffer = true;
< }
<
595c291
< skidInsert(tid);
---
> skidBuffer.push(*fromRename);
597c293,295
< dispatchStatus[tid] = Blocked;
---
> // 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.
601,602c299,300
< void
< DefaultIEW<Impl>::unblock(unsigned tid)
---
> inline void
> SimpleIEW<Impl>::unblock()
604,605c302,307
< DPRINTF(IEW, "[tid:%i]: Reading instructions out of the skid "
< "buffer %u.\n",tid, tid);
---
> // 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();
607,613c309,316
< // If the skid bufffer is empty, signal back to previous stages to unblock.
< // Also switch status to running.
< if (skidBuffer[tid].empty()) {
< toRename->iewUnblock[tid] = true;
< wroteToTimeBuffer = true;
< DPRINTF(IEW, "[tid:%i]: Done unblocking.\n",tid);
< dispatchStatus[tid] = Running;
---
> // 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;
619c322
< DefaultIEW<Impl>::wakeDependents(DynInstPtr &inst)
---
> SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
624,629d326
< template<class Impl>
< void
< DefaultIEW<Impl>::rescheduleMemInst(DynInstPtr &inst)
< {
< instQueue.rescheduleMemInst(inst);
< }
633c330
< DefaultIEW<Impl>::replayMemInst(DynInstPtr &inst)
---
> SimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
635,636d331
< instQueue.replayMemInst(inst);
< }
638,659d332
< template<class Impl>
< void
< DefaultIEW<Impl>::instToCommit(DynInstPtr &inst)
< {
< // First check the time slot that this instruction will write
< // to. If there are free write ports at the time, then go ahead
< // and write the instruction to that time. If there are not,
< // keep looking back to see where's the first time there's a
< // free slot.
< while ((*iewQueue)[wbCycle].insts[wbNumInst]) {
< ++wbNumInst;
< if (wbNumInst == issueWidth) {
< ++wbCycle;
< wbNumInst = 0;
< }
<
< assert(wbCycle < 5);
< }
<
< // Add finished instruction to queue to commit.
< (*iewQueue)[wbCycle].insts[wbNumInst] = inst;
< (*iewQueue)[wbCycle].size++;
663,676d335
< unsigned
< DefaultIEW<Impl>::validInstsFromRename()
< {
< unsigned inst_count = 0;
<
< for (int i=0; i<fromRename->size; i++) {
< if (!fromRename->insts[i]->squashed)
< inst_count++;
< }
<
< return inst_count;
< }
<
< template<class Impl>
678c337
< DefaultIEW<Impl>::skidInsert(unsigned tid)
---
> SimpleIEW<Impl>::dispatchInsts()
680c339,341
< DynInstPtr inst = NULL;
---
> ////////////////////////////////////////
> // DISPATCH/ISSUE stage
> ////////////////////////////////////////
682,683c343,344
< while (!insts[tid].empty()) {
< inst = insts[tid].front();
---
> //Put into its own function?
> //Add instructions to IQ if there are any instructions there
685c346,349
< insts[tid].pop();
---
> // Check if there are any instructions coming from rename, and we're.
> // not squashing.
> if (fromRename->size > 0) {
> int insts_to_add = fromRename->size;
687,689c351,355
< DPRINTF(Decode,"[tid:%i]: Inserting [sn:%lli] PC:%#x into "
< "dispatch skidBuffer %i\n",tid, inst->seqNum,
< inst->readPC(),tid);
---
> // 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];
691,692c357,358
< skidBuffer[tid].push(inst);
< }
---
> // Make sure there's a valid instruction there.
> assert(inst);
694,696c360,361
< assert(skidBuffer[tid].size() <= skidBufferMax &&
< "Skidbuffer Exceeded Max Size");
< }
---
> DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
> inst->readPC());
698,702c363,374
< template<class Impl>
< int
< DefaultIEW<Impl>::skidCount()
< {
< int max=0;
---
> // 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()) {
> DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
> // Call function to start blocking.
> block();
> // Tell previous stage to stall.
> toRename->iewInfo.stall = true;
704c376,380
< list<unsigned>::iterator threads = (*activeThreads).begin();
---
> ++iewIQFullEvents;
> break;
> } else if (inst->isLoad()) {
> DPRINTF(IEW, "IEW: Issue: Memory instruction "
> "encountered, adding to LDSTQ.\n");
706,710c382,384
< while (threads != (*activeThreads).end()) {
< unsigned thread_count = skidBuffer[*threads++].size();
< if (max < thread_count)
< max = thread_count;
< }
---
> // Reserve a spot in the load store queue for this
> // memory access.
> ldstQueue.insertLoad(inst);
712,713c386,388
< return max;
< }
---
> ++iewDispLoadInsts;
> } else if (inst->isStore()) {
> ldstQueue.insertStore(inst);
715,719c390,393
< template<class Impl>
< bool
< DefaultIEW<Impl>::skidsEmpty()
< {
< list<unsigned>::iterator threads = (*activeThreads).begin();
---
> ++iewDispStoreInsts;
> } else if (inst->isNonSpeculative()) {
> DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
> "encountered, skipping.\n");
721,1106c395
< while (threads != (*activeThreads).end()) {
< if (!skidBuffer[*threads++].empty())
< return false;
< }
<
< return true;
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::updateStatus()
< {
< bool any_unblocking = false;
<
< list<unsigned>::iterator threads = (*activeThreads).begin();
<
< threads = (*activeThreads).begin();
<
< while (threads != (*activeThreads).end()) {
< unsigned tid = *threads++;
<
< if (dispatchStatus[tid] == Unblocking) {
< any_unblocking = true;
< break;
< }
< }
<
< // If there are no ready instructions waiting to be scheduled by the IQ,
< // and there's no stores waiting to write back, and dispatch is not
< // unblocking, then there is no internal activity for the IEW stage.
< if (_status == Active && !instQueue.hasReadyInsts() &&
< !ldstQueue.willWB() && !any_unblocking) {
< DPRINTF(IEW, "IEW switching to idle\n");
<
< deactivateStage();
<
< _status = Inactive;
< } else if (_status == Inactive && (instQueue.hasReadyInsts() ||
< ldstQueue.willWB() ||
< any_unblocking)) {
< // Otherwise there is internal activity. Set to active.
< DPRINTF(IEW, "IEW switching to active\n");
<
< activateStage();
<
< _status = Active;
< }
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::resetEntries()
< {
< instQueue.resetEntries();
< ldstQueue.resetEntries();
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::readStallSignals(unsigned tid)
< {
< if (fromCommit->commitBlock[tid]) {
< stalls[tid].commit = true;
< }
<
< if (fromCommit->commitUnblock[tid]) {
< assert(stalls[tid].commit);
< stalls[tid].commit = false;
< }
< }
<
< template <class Impl>
< bool
< DefaultIEW<Impl>::checkStall(unsigned tid)
< {
< bool ret_val(false);
<
< if (stalls[tid].commit) {
< DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid);
< ret_val = true;
< } else if (instQueue.isFull(tid)) {
< DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid);
< ret_val = true;
< } else if (ldstQueue.isFull(tid)) {
< DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid);
<
< if (ldstQueue.numLoads(tid) > 0 ) {
<
< DPRINTF(IEW,"[tid:%i]: LSQ oldest load: [sn:%i] \n",
< tid,ldstQueue.getLoadHeadSeqNum(tid));
< }
<
< if (ldstQueue.numStores(tid) > 0) {
<
< DPRINTF(IEW,"[tid:%i]: LSQ oldest store: [sn:%i] \n",
< tid,ldstQueue.getStoreHeadSeqNum(tid));
< }
<
< ret_val = true;
< } else if (ldstQueue.isStalled(tid)) {
< DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid);
< ret_val = true;
< }
<
< return ret_val;
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::checkSignalsAndUpdate(unsigned tid)
< {
< // Check if there's a squash signal, squash if there is
< // Check stall signals, block if there is.
< // If status was Blocked
< // if so then go to unblocking
< // If status was Squashing
< // check if squashing is not high. Switch to running this cycle.
<
< readStallSignals(tid);
<
< if (fromCommit->commitInfo[tid].squash) {
< squash(tid);
<
< if (dispatchStatus[tid] == Blocked ||
< dispatchStatus[tid] == Unblocking) {
< toRename->iewUnblock[tid] = true;
< wroteToTimeBuffer = true;
< }
<
< dispatchStatus[tid] = Squashing;
<
< fetchRedirect[tid] = false;
< return;
< }
<
< if (fromCommit->commitInfo[tid].robSquashing) {
< DPRINTF(IEW, "[tid:%i]: ROB is still squashing.\n");
<
< dispatchStatus[tid] = Squashing;
<
< return;
< }
<
< if (checkStall(tid)) {
< block(tid);
< dispatchStatus[tid] = Blocked;
< return;
< }
<
< if (dispatchStatus[tid] == Blocked) {
< // Status from previous cycle was blocked, but there are no more stall
< // conditions. Switch over to unblocking.
< DPRINTF(IEW, "[tid:%i]: Done blocking, switching to unblocking.\n",
< tid);
<
< dispatchStatus[tid] = Unblocking;
<
< unblock(tid);
<
< return;
< }
<
< if (dispatchStatus[tid] == Squashing) {
< // Switch status to running if rename isn't being told to block or
< // squash this cycle.
< DPRINTF(IEW, "[tid:%i]: Done squashing, switching to running.\n",
< tid);
<
< dispatchStatus[tid] = Running;
<
< return;
< }
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::sortInsts()
< {
< int insts_from_rename = fromRename->size;
< #ifdef DEBUG
< for (int i = 0; i < numThreads; i++)
< assert(insts[i].empty());
< #endif
< for (int i = 0; i < insts_from_rename; ++i) {
< insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
< }
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::wakeCPU()
< {
< cpu->wakeCPU();
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::activityThisCycle()
< {
< DPRINTF(Activity, "Activity this cycle.\n");
< cpu->activityThisCycle();
< }
<
< template <class Impl>
< inline void
< DefaultIEW<Impl>::activateStage()
< {
< DPRINTF(Activity, "Activating stage.\n");
< cpu->activateStage(FullCPU::IEWIdx);
< }
<
< template <class Impl>
< inline void
< DefaultIEW<Impl>::deactivateStage()
< {
< DPRINTF(Activity, "Deactivating stage.\n");
< cpu->deactivateStage(FullCPU::IEWIdx);
< }
<
< template<class Impl>
< void
< DefaultIEW<Impl>::dispatch(unsigned tid)
< {
< // If status is Running or idle,
< // call dispatchInsts()
< // If status is Unblocking,
< // buffer any instructions coming from rename
< // continue trying to empty skid buffer
< // check if stall conditions have passed
<
< if (dispatchStatus[tid] == Blocked) {
< ++iewBlockCycles;
<
< } else if (dispatchStatus[tid] == Squashing) {
< ++iewSquashCycles;
< }
<
< // Dispatch should try to dispatch as many instructions as its bandwidth
< // will allow, as long as it is not currently blocked.
< if (dispatchStatus[tid] == Running ||
< dispatchStatus[tid] == Idle) {
< DPRINTF(IEW, "[tid:%i] Not blocked, so attempting to run "
< "dispatch.\n", tid);
<
< dispatchInsts(tid);
< } else if (dispatchStatus[tid] == Unblocking) {
< // Make sure that the skid buffer has something in it if the
< // status is unblocking.
< assert(!skidsEmpty());
<
< // If the status was unblocking, then instructions from the skid
< // buffer were used. Remove those instructions and handle
< // the rest of unblocking.
< dispatchInsts(tid);
<
< ++iewUnblockCycles;
<
< if (validInstsFromRename() && dispatchedAllInsts) {
< // Add the current inputs to the skid buffer so they can be
< // reprocessed when this stage unblocks.
< skidInsert(tid);
< }
<
< unblock(tid);
< }
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::dispatchInsts(unsigned tid)
< {
< dispatchedAllInsts = true;
<
< // Obtain instructions from skid buffer if unblocking, or queue from rename
< // otherwise.
< std::queue<DynInstPtr> &insts_to_dispatch =
< dispatchStatus[tid] == Unblocking ?
< skidBuffer[tid] : insts[tid];
<
< int insts_to_add = insts_to_dispatch.size();
<
< DynInstPtr inst;
< bool add_to_iq = false;
< int dis_num_inst = 0;
<
< // Loop through the instructions, putting them in the instruction
< // queue.
< for ( ; dis_num_inst < insts_to_add &&
< dis_num_inst < issueReadWidth;
< ++dis_num_inst)
< {
< inst = insts_to_dispatch.front();
<
< if (dispatchStatus[tid] == Unblocking) {
< DPRINTF(IEW, "[tid:%i]: Issue: Examining instruction from skid "
< "buffer\n", tid);
< }
<
< // Make sure there's a valid instruction there.
< assert(inst);
<
< DPRINTF(IEW, "[tid:%i]: Issue: Adding PC %#x [sn:%lli] [tid:%i] to "
< "IQ.\n",
< tid, inst->readPC(), inst->seqNum, inst->threadNumber);
<
< // 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.
<
< // Check for squashed instructions.
< if (inst->isSquashed()) {
< DPRINTF(IEW, "[tid:%i]: Issue: Squashed instruction encountered, "
< "not adding to IQ.\n", tid);
<
< ++iewDispSquashedInsts;
<
< insts_to_dispatch.pop();
<
< //Tell Rename That An Instruction has been processed
< if (inst->isLoad() || inst->isStore()) {
< toRename->iewInfo[tid].dispatchedToLSQ++;
< }
< toRename->iewInfo[tid].dispatched++;
<
< continue;
< }
<
< // Check for full conditions.
< if (instQueue.isFull(tid)) {
< DPRINTF(IEW, "[tid:%i]: Issue: IQ has become full.\n", tid);
<
< // Call function to start blocking.
< block(tid);
<
< // Set unblock to false. Special case where we are using
< // skidbuffer (unblocking) instructions but then we still
< // get full in the IQ.
< toRename->iewUnblock[tid] = false;
<
< dispatchedAllInsts = false;
<
< ++iewIQFullEvents;
< break;
< } else if (ldstQueue.isFull(tid)) {
< DPRINTF(IEW, "[tid:%i]: Issue: LSQ has become full.\n",tid);
<
< // Call function to start blocking.
< block(tid);
<
< // Set unblock to false. Special case where we are using
< // skidbuffer (unblocking) instructions but then we still
< // get full in the IQ.
< toRename->iewUnblock[tid] = false;
<
< dispatchedAllInsts = false;
<
< ++iewLSQFullEvents;
< break;
< }
<
< // Otherwise issue the instruction just fine.
< if (inst->isLoad()) {
< DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
< "encountered, adding to LSQ.\n", tid);
<
< // Reserve a spot in the load store queue for this
< // memory access.
< ldstQueue.insertLoad(inst);
<
< ++iewDispLoadInsts;
<
< add_to_iq = true;
<
< toRename->iewInfo[tid].dispatchedToLSQ++;
< } else if (inst->isStore()) {
< DPRINTF(IEW, "[tid:%i]: Issue: Memory instruction "
< "encountered, adding to LSQ.\n", tid);
<
< ldstQueue.insertStore(inst);
<
< ++iewDispStoreInsts;
<
< if (inst->isStoreConditional()) {
< // Store conditionals need to be set as "canCommit()"
< // so that commit can process them when they reach the
< // head of commit.
---
> // Same hack as with stores.
1107a397,398
>
> // Specificall insert it as nonspeculative.
1109d399
< add_to_iq = false;
1112,1114d401
< } else {
< add_to_iq = true;
< }
1116,1126c403,406
< toRename->iewInfo[tid].dispatchedToLSQ++;
< #if FULL_SYSTEM
< } else if (inst->isMemBarrier() || inst->isWriteBarrier()) {
< // Same as non-speculative stores.
< inst->setCanCommit();
< instQueue.insertBarrier(inst);
< add_to_iq = false;
< #endif
< } else if (inst->isNonSpeculative()) {
< DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
< "encountered, skipping.\n", tid);
---
> continue;
> } else if (inst->isNop()) {
> DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
> ", skipping.\n");
1128,1129c408,410
< // Same as non-speculative stores.
< inst->setCanCommit();
---
> inst->setIssued();
> inst->setExecuted();
> inst->setCanCommit();
1131,1132c412
< // Specifically insert it as nonspeculative.
< instQueue.insertNonSpec(inst);
---
> instQueue.advanceTail(inst);
1134c414,418
< ++iewDispNonSpecInsts;
---
> continue;
> } else if (inst->isExecuted()) {
> assert(0 && "Instruction shouldn't be executed.\n");
> DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
> "skipping.\n");
1136,1139c420,421
< add_to_iq = false;
< } else if (inst->isNop()) {
< DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
< "skipping.\n", tid);
---
> inst->setIssued();
> inst->setCanCommit();
1141,1143c423
< inst->setIssued();
< inst->setExecuted();
< inst->setCanCommit();
---
> instQueue.advanceTail(inst);
1145c425,426
< instQueue.recordProducer(inst);
---
> continue;
> }
1147c428,430
< exeNop[tid]++;
---
> // If the instruction queue is not full, then add the
> // instruction.
> instQueue.insert(fromRename->insts[inst_num]);
1149,1162c432
< add_to_iq = false;
< } else if (inst->isExecuted()) {
< assert(0 && "Instruction shouldn't be executed.\n");
< DPRINTF(IEW, "Issue: Executed branch encountered, "
< "skipping.\n");
<
< inst->setIssued();
< inst->setCanCommit();
<
< instQueue.recordProducer(inst);
<
< add_to_iq = false;
< } else {
< add_to_iq = true;
---
> ++iewDispatchedInsts;
1164,1175d433
<
< // If the instruction queue is not full, then add the
< // instruction.
< if (add_to_iq) {
< instQueue.insert(inst);
< }
<
< insts_to_dispatch.pop();
<
< toRename->iewInfo[tid].dispatched++;
<
< ++iewDispatchedInsts;
1177,1190d434
<
< if (!insts_to_dispatch.empty()) {
< DPRINTF(IEW,"[tid:%i]: Issue: Bandwidth Full. Blocking.\n");
< block(tid);
< toRename->iewUnblock[tid] = false;
< }
<
< if (dispatchStatus[tid] == Idle && dis_num_inst) {
< dispatchStatus[tid] = Running;
<
< updatedQueues = true;
< }
<
< dis_num_inst = 0;
1195c439
< DefaultIEW<Impl>::printAvailableInsts()
---
> SimpleIEW<Impl>::executeInsts()
1197c441,443
< int inst = 0;
---
> ////////////////////////////////////////
> //EXECUTE/WRITEBACK stage
> ////////////////////////////////////////
1199c445,451
< cout << "Available Instructions: ";
---
> //Put into its own function?
> //Similarly should probably have separate execution for int vs FP.
> // Above comment is handled by the issue queue only issuing a valid
> // mix of int/fp instructions.
> //Actually okay to just have one execution, buuuuuut will need
> //somewhere that defines the execution latency of all instructions.
> // @todo: Move to the FU pool used in the current full cpu.
1201c453,456
< while (fromIssue->insts[inst]) {
---
> int fu_usage = 0;
> bool fetch_redirect = false;
> int inst_slot = 0;
> int time_slot = 0;
1203,1233d457
< if (inst%3==0) cout << "\n\t";
<
< cout << "PC: " << fromIssue->insts[inst]->readPC()
< << " TN: " << fromIssue->insts[inst]->threadNumber
< << " SN: " << fromIssue->insts[inst]->seqNum << " | ";
<
< inst++;
<
< }
<
< cout << "\n";
< }
<
< template <class Impl>
< void
< DefaultIEW<Impl>::executeInsts()
< {
< wbNumInst = 0;
< wbCycle = 0;
<
< list<unsigned>::iterator threads = (*activeThreads).begin();
<
< while (threads != (*activeThreads).end()) {
< unsigned tid = *threads++;
< fetchRedirect[tid] = false;
< }
<
< #if 0
< printAvailableInsts();
< #endif
<
1235,1238c459,463
< int insts_to_execute = fromIssue->size;
< int inst_num = 0;
< for (; inst_num < insts_to_execute;
< ++inst_num) {
---
> for (int inst_num = 0;
> fu_usage < executeWidth && /* Haven't exceeded available FU's. */
> inst_num < issueWidth &&
> fromIssue->insts[inst_num];
> ++inst_num) {
1240c465
< DPRINTF(IEW, "Execute: Executing instructions from IQ.\n");
---
> DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
1242c467,468
< DynInstPtr inst = instQueue.getInstToExecute();
---
> // Get instruction from issue's queue.
> DynInstPtr inst = fromIssue->insts[inst_num];
1244,1245c470
< DPRINTF(IEW, "Execute: Processing PC %#x, [tid:%i] [sn:%i].\n",
< inst->readPC(), inst->threadNumber,inst->seqNum);
---
> DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
1247a473
> // and don't count it towards the FU usage.
1249c475
< DPRINTF(IEW, "Execute: Instruction was squashed.\n");
---
> DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
1255,1257c481
< // Not sure if I should set this here or just let commit try to
< // commit any squashed instructions. I like the latter a bit more.
< inst->setCanCommit();
---
> toCommit->insts[inst_num] = inst;
1264c488
< Fault fault = NoFault;
---
> inst->setExecuted();
1265a490,492
> // If an instruction is executed, then count it towards FU usage.
> ++fu_usage;
>
1269,1271c496,497
< if (inst->isMemRef() &&
< (!inst->isDataPrefetch() && !inst->isInstPrefetch())) {
< DPRINTF(IEW, "Execute: Calculating address for memory "
---
> if (inst->isMemRef()) {
> DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
1276,1278c502,504
< // Loads will mark themselves as executed, and their writeback
< // event adds the instruction to the queue to commit
< fault = ldstQueue.executeLoad(inst);
---
> ldstQueue.executeLoad(inst);
>
> ++iewExecLoadInsts;
1282,1291c508
< // If the store had a fault then it may not have a mem req
< if (inst->req && !(inst->req->flags & LOCKED)) {
< inst->setExecuted();
<
< instToCommit(inst);
< }
<
< // Store conditionals will mark themselves as
< // executed, and their writeback event will add the
< // instruction to the queue to commit.
---
> ++iewExecStoreInsts;
1293c510
< panic("Unexpected memory type!\n");
---
> panic("IEW: Unexpected memory type!\n");
1299,1301c516
< inst->setExecuted();
<
< instToCommit(inst);
---
> ++iewExecutedInsts;
1304c519,534
< updateExeInstStats(inst);
---
> // First check the time slot that this instruction will write
> // to. If there are free write ports at the time, then go ahead
> // and write the instruction to that time. If there are not,
> // keep looking back to see where's the first time there's a
> // free slot. What happens if you run out of free spaces?
> // For now naively assume that all instructions take one cycle.
> // Otherwise would have to look into the time buffer based on the
> // latency of the instruction.
> (*iewQueue)[time_slot].insts[inst_slot];
> while ((*iewQueue)[time_slot].insts[inst_slot]) {
> if (inst_slot < issueWidth) {
> ++inst_slot;
> } else {
> ++time_slot;
> inst_slot = 0;
> }
1306,1309c536,537
< // Check if branch prediction was correct, if not then we need
< // to tell commit to squash in flight instructions. Only
< // handle this if there hasn't already been something that
< // redirects fetch in this group of instructions.
---
> assert(time_slot < 5);
> }
1311,1314c539
< // This probably needs to prioritize the redirects if a different
< // scheduler is used. Currently the scheduler schedules the oldest
< // instruction first, so the branch resolution order will be correct.
< unsigned tid = inst->threadNumber;
---
> // May actually have to work this out, especially with loads and stores
1316c541,543
< if (!fetchRedirect[tid]) {
---
> // Add finished instruction to queue to commit.
> (*iewQueue)[time_slot].insts[inst_slot] = inst;
> (*iewQueue)[time_slot].size++;
1317a545,550
> // Check if branch was correct. This check happens after the
> // instruction is added to the queue because even if the branch
> // is mispredicted, the branch instruction itself is still valid.
> // Only handle this if there hasn't already been something that
> // redirects fetch in this group of instructions.
> if (!fetch_redirect) {
1319c552
< fetchRedirect[tid] = true;
---
> fetch_redirect = true;
1321,1322c554,555
< DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
< DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
---
> DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
> DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
1326c559
< squashDueToBranch(inst, tid);
---
> squashDueToBranch(inst);
1330,1331d562
< } else {
< predictedNotTakenIncorrect++;
1333,1334c564,565
< } else if (ldstQueue.violation(tid)) {
< fetchRedirect[tid] = true;
---
> } else if (ldstQueue.violation()) {
> fetch_redirect = true;
1336,1340c567,568
< // If there was an ordering violation, then get the
< // DynInst that caused the violation. Note that this
< // clears the violation signal.
< DynInstPtr violator;
< violator = ldstQueue.getMemDepViolator(tid);
---
> // Get the DynInst that caused the violation.
> DynInstPtr violator = ldstQueue.getMemDepViolator();
1342c570
< DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
---
> DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: "
1350c578
< squashDueToMemOrder(inst,tid);
---
> squashDueToMem(inst);
1353,1361d580
< } else if (ldstQueue.loadBlocked(tid) &&
< !ldstQueue.isLoadBlockedHandled(tid)) {
< fetchRedirect[tid] = true;
<
< DPRINTF(IEW, "Load operation couldn't execute because the "
< "memory system is blocked. PC: %#x [sn:%lli]\n",
< inst->readPC(), inst->seqNum);
<
< squashDueToMemBlocked(inst, tid);
1365,1379d583
<
< if (inst_num) {
< if (exeStatus == Idle) {
< exeStatus = Running;
< }
<
< updatedQueues = true;
<
< cpu->activityThisCycle();
< }
<
< // Need to reset this in case a writeback event needs to write into the
< // iew queue. That way the writeback event will write into the correct
< // spot in the queue.
< wbNumInst = 0;
1382c586
< template <class Impl>
---
> template<class Impl>
1384c588
< DefaultIEW<Impl>::writebackInsts()
---
> SimpleIEW<Impl>::tick()
1386,1394c590
< // Loop through the head of the time buffer and wake any
< // dependents. These instructions are about to write back. Also
< // mark scoreboard that this instruction is finally complete.
< // Either have IEW have direct access to scoreboard, or have this
< // as part of backwards communication.
< for (int inst_num = 0; inst_num < issueWidth &&
< toCommit->insts[inst_num]; inst_num++) {
< DynInstPtr inst = toCommit->insts[inst_num];
< int tid = inst->threadNumber;
---
> // Considering putting all the state-determining stuff in this section.
1396,1397c592,595
< DPRINTF(IEW, "Sending instructions to commit, PC %#x.\n",
< inst->readPC());
---
> // Try to fill up issue queue with as many instructions as bandwidth
> // allows.
> // Decode should try to execute as many instructions as its bandwidth
> // will allow, as long as it is not currently blocked.
1399c597,601
< iewInstsToCommit[tid]++;
---
> // Check if the stage is in a running status.
> if (_status != Blocked && _status != Squashing) {
> DPRINTF(IEW, "IEW: Status is not blocked, attempting to run "
> "stage.\n");
> iew();
1401,1407c603,606
< // Some instructions will be sent to commit without having
< // executed because they need commit to handle them.
< // E.g. Uncached loads have not actually executed when they
< // are first sent to commit. Instead commit must tell the LSQ
< // when it's ready to execute the uncached load.
< if (!inst->isSquashed() && inst->isExecuted()) {
< int dependents = instQueue.wakeDependents(inst);
---
> // If it's currently unblocking, check to see if it should switch
> // to running.
> if (_status == Unblocking) {
> unblock();
1409,1418c608
< for (int i = 0; i < inst->numDestRegs(); i++) {
< //mark as Ready
< DPRINTF(IEW,"Setting Destination Register %i\n",
< inst->renamedDestRegIdx(i));
< scoreboard->setReg(inst->renamedDestRegIdx(i));
< }
<
< producerInst[tid]++;
< consumerInst[tid]+= dependents;
< writebackCount[tid]++;
---
> ++iewUnblockCycles;
1420,1421c610
< }
< }
---
> } else if (_status == Squashing) {
1423,1428c612
< template<class Impl>
< void
< DefaultIEW<Impl>::tick()
< {
< wbNumInst = 0;
< wbCycle = 0;
---
> DPRINTF(IEW, "IEW: Still squashing.\n");
1430,1431c614,619
< wroteToTimeBuffer = false;
< updatedQueues = false;
---
> // Check if stage should remain squashing. Stop squashing if the
> // squash signal clears.
> if (!fromCommit->commitInfo.squash &&
> !fromCommit->commitInfo.robSquashing) {
> DPRINTF(IEW, "IEW: Done squashing, changing status to "
> "running.\n");
1433c621,625
< sortInsts();
---
> _status = Running;
> instQueue.stopSquash();
> } else {
> instQueue.doSquash();
> }
1435,1436c627,630
< // Free function units marked as being freed this cycle.
< fuPool->processFreeUnits();
---
> ++iewSquashCycles;
> } else if (_status == Blocked) {
> // Continue to tell previous stage to stall.
> toRename->iewInfo.stall = true;
1438c632,637
< list<unsigned>::iterator threads = (*activeThreads).begin();
---
> // Check if possible stall conditions have cleared.
> if (!fromCommit->commitInfo.stall &&
> !instQueue.isFull()) {
> DPRINTF(IEW, "IEW: Stall signals cleared, going to unblock.\n");
> _status = Unblocking;
> }
1440,1442c639,643
< // Check stall and squash signals, dispatch any instructions.
< while (threads != (*activeThreads).end()) {
< unsigned tid = *threads++;
---
> // If there's still instructions coming from rename, continue to
> // put them on the skid buffer.
> if (fromRename->size == 0) {
> block();
> }
1444c645,648
< DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
---
> if (fromCommit->commitInfo.squash ||
> fromCommit->commitInfo.robSquashing) {
> squash();
> }
1446,1447c650
< checkSignalsAndUpdate(tid);
< dispatch(tid);
---
> ++iewBlockCycles;
1450,1451c653,656
< if (exeStatus != Squashing) {
< executeInsts();
---
> // @todo: Maybe put these at the beginning, so if it's idle it can
> // return early.
> // Write back number of free IQ entries here.
> toRename->iewInfo.freeIQEntries = instQueue.numFreeEntries();
1453,1474d657
< writebackInsts();
<
< // Have the instruction queue try to schedule any ready instructions.
< // (In actuality, this scheduling is for instructions that will
< // be executed next cycle.)
< instQueue.scheduleReadyInsts();
<
< // Also should advance its own time buffers if the stage ran.
< // Not the best place for it, but this works (hopefully).
< issueToExecQueue.advance();
< }
<
< bool broadcast_free_entries = false;
<
< if (updatedQueues || exeStatus == Running || updateLSQNextCycle) {
< exeStatus = Idle;
< updateLSQNextCycle = false;
<
< broadcast_free_entries = true;
< }
<
< // Writeback any stores using any leftover bandwidth.
1480a664,668
> if (!fromCommit->commitInfo.squash &&
> !fromCommit->commitInfo.robSquashing) {
> ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
> ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
> }
1482,1484c670,672
< threads = (*activeThreads).begin();
< while (threads != (*activeThreads).end()) {
< unsigned tid = (*threads++);
---
> if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
> instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
> }
1486c674,676
< DPRINTF(IEW,"Processing [tid:%i]\n",tid);
---
> DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
> instQueue.numFreeEntries());
> }
1488,1490c678,692
< if (fromCommit->commitInfo[tid].doneSeqNum != 0 &&
< !fromCommit->commitInfo[tid].squash &&
< !fromCommit->commitInfo[tid].robSquashing) {
---
> template<class Impl>
> void
> SimpleIEW<Impl>::iew()
> {
> // Might want to put all state checks in the tick() function.
> // Check if being told to stall from commit.
> if (fromCommit->commitInfo.stall) {
> block();
> return;
> } else if (fromCommit->commitInfo.squash ||
> fromCommit->commitInfo.robSquashing) {
> // Also check if commit is telling this stage to squash.
> squash();
> return;
> }
1492c694
< ldstQueue.commitStores(fromCommit->commitInfo[tid].doneSeqNum,tid);
---
> dispatchInsts();
1494c696,697
< ldstQueue.commitLoads(fromCommit->commitInfo[tid].doneSeqNum,tid);
---
> // Have the instruction queue try to schedule any ready instructions.
> instQueue.scheduleReadyInsts();
1496,1498c699
< updateLSQNextCycle = true;
< instQueue.commit(fromCommit->commitInfo[tid].doneSeqNum,tid);
< }
---
> executeInsts();
1500c701,711
< if (fromCommit->commitInfo[tid].nonSpecSeqNum != 0) {
---
> // Loop through the head of the time buffer and wake any dependents.
> // These instructions are about to write back. In the simple model
> // this loop can really happen within the previous loop, but when
> // instructions have actual latencies, this loop must be separate.
> // Also mark scoreboard that this instruction is finally complete.
> // Either have IEW have direct access to rename map, or have this as
> // part of backwards communication.
> for (int inst_num = 0; inst_num < issueWidth &&
> toCommit->insts[inst_num]; inst_num++)
> {
> DynInstPtr inst = toCommit->insts[inst_num];
1502,1509c713,714
< //DPRINTF(IEW,"NonspecInst from thread %i",tid);
< if (fromCommit->commitInfo[tid].uncached) {
< instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
< } else {
< instQueue.scheduleNonSpec(
< fromCommit->commitInfo[tid].nonSpecSeqNum);
< }
< }
---
> DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
> inst->readPC());
1511,1515c716,717
< if (broadcast_free_entries) {
< toFetch->iewInfo[tid].iqCount =
< instQueue.getCount(tid);
< toFetch->iewInfo[tid].ldstqCount =
< ldstQueue.getCount(tid);
---
> if(!inst->isSquashed()) {
> instQueue.wakeDependents(inst);
1517,1524c719,722
< toRename->iewInfo[tid].usedIQ = true;
< toRename->iewInfo[tid].freeIQEntries =
< instQueue.numFreeEntries();
< toRename->iewInfo[tid].usedLSQ = true;
< toRename->iewInfo[tid].freeLSQEntries =
< ldstQueue.numFreeEntries(tid);
<
< wroteToTimeBuffer = true;
---
> for (int i = 0; i < inst->numDestRegs(); i++)
> {
> renameMap->markAsReady(inst->renamedDestRegIdx(i));
> }
1526,1528d723
<
< DPRINTF(IEW, "[tid:%i], Dispatch dispatched %i instructions.\n",
< tid, toRename->iewInfo[tid].dispatched);
1531,1541c726,728
< DPRINTF(IEW, "IQ has %i free entries (Can schedule: %i). "
< "LSQ has %i free entries.\n",
< instQueue.numFreeEntries(), instQueue.hasReadyInsts(),
< ldstQueue.numFreeEntries());
<
< updateStatus();
<
< if (wroteToTimeBuffer) {
< DPRINTF(Activity, "Activity this cycle.\n");
< cpu->activityThisCycle();
< }
---
> // Also should advance its own time buffers if the stage ran.
> // Not the best place for it, but this works (hopefully).
> issueToExecQueue.advance();
1544c731,732
< template <class Impl>
---
> #if !FULL_SYSTEM
> template<class Impl>
1546c734
< DefaultIEW<Impl>::updateExeInstStats(DynInstPtr &inst)
---
> SimpleIEW<Impl>::lsqWriteback()
1548,1577c736
< int thread_number = inst->threadNumber;
<
< //
< // Pick off the software prefetches
< //
< #ifdef TARGET_ALPHA
< if (inst->isDataPrefetch())
< exeSwp[thread_number]++;
< else
< iewExecutedInsts++;
< #else
< iewExecutedInsts[thread_number]++;
< #endif
<
< //
< // Control operations
< //
< if (inst->isControl())
< exeBranches[thread_number]++;
<
< //
< // Memory operations
< //
< if (inst->isMemRef()) {
< exeRefs[thread_number]++;
<
< if (inst->isLoad()) {
< iewExecLoadInsts[thread_number]++;
< }
< }
---
> ldstQueue.writebackAllInsts();
1578a738
> #endif