summaryrefslogtreecommitdiff
path: root/src/cpu/o3/iew_impl.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu/o3/iew_impl.hh')
-rw-r--r--src/cpu/o3/iew_impl.hh736
1 files changed, 736 insertions, 0 deletions
diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh
new file mode 100644
index 000000000..85217dd10
--- /dev/null
+++ b/src/cpu/o3/iew_impl.hh
@@ -0,0 +1,736 @@
+/*
+ * Copyright (c) 2004-2005 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// @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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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>
+void
+SimpleIEW<Impl>::setRenameMap(RenameMap *rm_ptr)
+{
+ DPRINTF(IEW, "IEW: Setting rename map pointer.\n");
+ renameMap = rm_ptr;
+}
+
+template<class Impl>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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(TheISA::MachInst));
+}
+
+template<class Impl>
+void
+SimpleIEW<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>
+void
+SimpleIEW<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 void
+SimpleIEW<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>
+void
+SimpleIEW<Impl>::wakeDependents(DynInstPtr &inst)
+{
+ instQueue.wakeDependents(inst);
+}
+
+
+template<class Impl>
+void
+SimpleIEW<Impl>::instToCommit(DynInstPtr &inst)
+{
+
+}
+
+template <class Impl>
+void
+SimpleIEW<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()) {
+ DPRINTF(IEW, "IEW: Issue: IQ has become full.\n");
+ // Call function to start blocking.
+ block();
+ // Tell previous stage to stall.
+ toRename->iewInfo.stall = true;
+
+ ++iewIQFullEvents;
+ break;
+ } else if (inst->isLoad()) {
+ DPRINTF(IEW, "IEW: Issue: Memory instruction "
+ "encountered, adding to LDSTQ.\n");
+
+ // Reserve a spot in the load store queue for this
+ // memory access.
+ ldstQueue.insertLoad(inst);
+
+ ++iewDispLoadInsts;
+ } else if (inst->isStore()) {
+ ldstQueue.insertStore(inst);
+
+ ++iewDispStoreInsts;
+ } else if (inst->isNonSpeculative()) {
+ DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
+ "encountered, skipping.\n");
+
+ // Same hack as with stores.
+ inst->setCanCommit();
+
+ // Specificall insert it as nonspeculative.
+ instQueue.insertNonSpec(inst);
+
+ ++iewDispNonSpecInsts;
+
+ continue;
+ } else if (inst->isNop()) {
+ DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
+ ", skipping.\n");
+
+ inst->setIssued();
+ inst->setExecuted();
+ inst->setCanCommit();
+
+ instQueue.advanceTail(inst);
+
+ continue;
+ } else if (inst->isExecuted()) {
+ assert(0 && "Instruction shouldn't be executed.\n");
+ DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
+ "skipping.\n");
+
+ inst->setIssued();
+ inst->setCanCommit();
+
+ instQueue.advanceTail(inst);
+
+ continue;
+ }
+
+ // If the instruction queue is not full, then add the
+ // instruction.
+ instQueue.insert(fromRename->insts[inst_num]);
+
+ ++iewDispatchedInsts;
+ }
+ }
+}
+
+template <class Impl>
+void
+SimpleIEW<Impl>::executeInsts()
+{
+ ////////////////////////////////////////
+ //EXECUTE/WRITEBACK stage
+ ////////////////////////////////////////
+
+ //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.
+
+ int fu_usage = 0;
+ bool fetch_redirect = false;
+ int inst_slot = 0;
+ int time_slot = 0;
+
+ // Execute/writeback any instructions that are available.
+ for (int inst_num = 0;
+ fu_usage < executeWidth && /* Haven't exceeded available FU's. */
+ inst_num < issueWidth &&
+ fromIssue->insts[inst_num];
+ ++inst_num) {
+
+ DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
+
+ // Get instruction from issue's queue.
+ DynInstPtr inst = fromIssue->insts[inst_num];
+
+ DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
+
+ // Check if the instruction is squashed; if so then skip it
+ // and don't count it towards the FU usage.
+ if (inst->isSquashed()) {
+ DPRINTF(IEW, "IEW: Execute: Instruction was squashed.\n");
+
+ // Consider this instruction executed so that commit can go
+ // ahead and retire the instruction.
+ inst->setExecuted();
+
+ toCommit->insts[inst_num] = inst;
+
+ ++iewExecSquashedInsts;
+
+ continue;
+ }
+
+ inst->setExecuted();
+
+ // If an instruction is executed, then count it towards FU usage.
+ ++fu_usage;
+
+ // Execute instruction.
+ // Note that if the instruction faults, it will be handled
+ // at the commit stage.
+ if (inst->isMemRef()) {
+ DPRINTF(IEW, "IEW: Execute: Calculating address for memory "
+ "reference.\n");
+
+ // Tell the LDSTQ to execute this instruction (if it is a load).
+ if (inst->isLoad()) {
+ ldstQueue.executeLoad(inst);
+
+ ++iewExecLoadInsts;
+ } else if (inst->isStore()) {
+ ldstQueue.executeStore(inst);
+
+ ++iewExecStoreInsts;
+ } else {
+ panic("IEW: Unexpected memory type!\n");
+ }
+
+ } else {
+ inst->execute();
+
+ ++iewExecutedInsts;
+ }
+
+ // 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;
+ }
+
+ assert(time_slot < 5);
+ }
+
+ // May actually have to work this out, especially with loads and stores
+
+ // Add finished instruction to queue to commit.
+ (*iewQueue)[time_slot].insts[inst_slot] = inst;
+ (*iewQueue)[time_slot].size++;
+
+ // 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) {
+ if (inst->mispredicted()) {
+ fetch_redirect = true;
+
+ DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
+ DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
+ inst->nextPC);
+
+ // If incorrect, then signal the ROB that it must be squashed.
+ squashDueToBranch(inst);
+
+ if (inst->predTaken()) {
+ predictedTakenIncorrect++;
+ }
+ } else if (ldstQueue.violation()) {
+ fetch_redirect = true;
+
+ // Get the DynInst that caused the violation.
+ DynInstPtr violator = ldstQueue.getMemDepViolator();
+
+ DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: "
+ "%#x, inst PC: %#x. Addr is: %#x.\n",
+ violator->readPC(), inst->readPC(), inst->physEffAddr);
+
+ // Tell the instruction queue that a violation has occured.
+ instQueue.violation(inst, violator);
+
+ // Squash.
+ squashDueToMem(inst);
+
+ ++memOrderViolationEvents;
+ }
+ }
+ }
+}
+
+template<class Impl>
+void
+SimpleIEW<Impl>::tick()
+{
+ // Considering putting all the state-determining stuff in this section.
+
+ // 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.
+
+ // 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();
+
+ // If it's currently unblocking, check to see if it should switch
+ // to running.
+ if (_status == Unblocking) {
+ unblock();
+
+ ++iewUnblockCycles;
+ }
+ } else if (_status == Squashing) {
+
+ DPRINTF(IEW, "IEW: Still squashing.\n");
+
+ // 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");
+
+ _status = Running;
+ instQueue.stopSquash();
+ } else {
+ instQueue.doSquash();
+ }
+
+ ++iewSquashCycles;
+ } else if (_status == Blocked) {
+ // Continue to tell previous stage to stall.
+ toRename->iewInfo.stall = true;
+
+ // 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;
+ }
+
+ // If there's still instructions coming from rename, continue to
+ // put them on the skid buffer.
+ if (fromRename->size == 0) {
+ block();
+ }
+
+ if (fromCommit->commitInfo.squash ||
+ fromCommit->commitInfo.robSquashing) {
+ squash();
+ }
+
+ ++iewBlockCycles;
+ }
+
+ // @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();
+
+ ldstQueue.writebackStores();
+
+ // Check the committed load/store signals to see if there's a load
+ // or store to commit. Also check if it's being told to execute a
+ // nonspeculative instruction.
+ // This is pretty inefficient...
+ if (!fromCommit->commitInfo.squash &&
+ !fromCommit->commitInfo.robSquashing) {
+ ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
+ ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
+ }
+
+ if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
+ instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
+ }
+
+ DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
+ instQueue.numFreeEntries());
+}
+
+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;
+ }
+
+ dispatchInsts();
+
+ // Have the instruction queue try to schedule any ready instructions.
+ instQueue.scheduleReadyInsts();
+
+ executeInsts();
+
+ // 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];
+
+ DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
+ inst->readPC());
+
+ if(!inst->isSquashed()) {
+ instQueue.wakeDependents(inst);
+
+ for (int i = 0; i < inst->numDestRegs(); i++)
+ {
+ renameMap->markAsReady(inst->renamedDestRegIdx(i));
+ }
+ }
+ }
+
+ // Also should advance its own time buffers if the stage ran.
+ // Not the best place for it, but this works (hopefully).
+ issueToExecQueue.advance();
+}
+
+#if !FULL_SYSTEM
+template<class Impl>
+void
+SimpleIEW<Impl>::lsqWriteback()
+{
+ ldstQueue.writebackAllInsts();
+}
+#endif