summaryrefslogtreecommitdiff
path: root/cpu/beta_cpu/iew_impl.hh
diff options
context:
space:
mode:
Diffstat (limited to 'cpu/beta_cpu/iew_impl.hh')
-rw-r--r--cpu/beta_cpu/iew_impl.hh406
1 files changed, 278 insertions, 128 deletions
diff --git a/cpu/beta_cpu/iew_impl.hh b/cpu/beta_cpu/iew_impl.hh
index 521ce77f6..2bfd6bae9 100644
--- a/cpu/beta_cpu/iew_impl.hh
+++ b/cpu/beta_cpu/iew_impl.hh
@@ -38,6 +38,79 @@ SimpleIEW<Impl, IQ>::SimpleIEW(Params &params)
instQueue.setIssueToExecuteQueue(&issueToExecQueue);
}
+template <class Impl, class IQ>
+void
+SimpleIEW<Impl, IQ>::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, class IQ>
void
SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr)
@@ -158,7 +231,7 @@ SimpleIEW<Impl, IQ>::squash()
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::squash(DynInstPtr &inst)
+SimpleIEW<Impl, IQ>::squashDueToBranch(DynInstPtr &inst)
{
DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC: %#x.\n",
inst->PC);
@@ -167,119 +240,39 @@ SimpleIEW<Impl, IQ>::squash(DynInstPtr &inst)
_status = Squashing;
// Tell rename to squash through the time buffer.
- toRename->iewInfo.squash = true;
+ toCommit->squash = true;
// Also send PC update information back to prior stages.
- toRename->iewInfo.squashedSeqNum = inst->seqNum;
- toRename->iewInfo.mispredPC = inst->readPC();
- toRename->iewInfo.nextPC = inst->readCalcTarg();
- toRename->iewInfo.branchMispredict = true;
+ toCommit->squashedSeqNum = inst->seqNum;
+ toCommit->mispredPC = inst->readPC();
+ toCommit->nextPC = inst->readCalcTarg();
+ toCommit->branchMispredict = true;
// Prediction was incorrect, so send back inverse.
- toRename->iewInfo.branchTaken = !(inst->predTaken());
+ toCommit->branchTaken = inst->readCalcTarg() !=
+ (inst->readPC() + sizeof(MachInst));
+// toCommit->globalHist = inst->readGlobalHist();
}
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::tick()
+SimpleIEW<Impl, IQ>::squashDueToMem(DynInstPtr &inst)
{
- // 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();
- }
- } 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();
- }
-
- // Also should advance its own time buffers if the stage ran.
- // Not sure about this...
-// issueToExecQueue.advance();
- } 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->insts[0]) {
- block();
- }
-
- if (fromCommit->commitInfo.squash ||
- fromCommit->commitInfo.robSquashing) {
- squash();
- }
- }
-
- // @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();
-
- // 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.
- if (fromCommit->commitInfo.commitIsStore) {
- ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
- } else if (fromCommit->commitInfo.commitIsLoad) {
- ldstQueue.commitLoads(fromCommit->commitInfo.doneSeqNum);
- }
-
- if (fromCommit->commitInfo.nonSpecSeqNum != 0) {
- instQueue.scheduleNonSpec(fromCommit->commitInfo.nonSpecSeqNum);
- }
+ 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;
- DPRINTF(IEW, "IEW: IQ has %i free entries.\n",
- instQueue.numFreeEntries());
+ // 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->readCalcTarg();
}
-template<class Impl, class IQ>
+template <class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::iew()
+SimpleIEW<Impl, IQ>::dispatchInsts()
{
- // 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;
- }
-
////////////////////////////////////////
// DISPATCH/ISSUE stage
////////////////////////////////////////
@@ -289,29 +282,36 @@ SimpleIEW<Impl, IQ>::iew()
// Check if there are any instructions coming from rename, and we're.
// not squashing.
- if (fromRename->insts[0] && _status != 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 < issueReadWidth; ++inst_num)
+ 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.
- if (!inst)
- break;
+ assert(inst);
DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
inst->readPC());
- // If it's a memory reference, don't put it in the
- // instruction queue. These will only be executed at commit.
- // Do the same for nonspeculative instructions and nops.
// 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");
@@ -320,6 +320,7 @@ SimpleIEW<Impl, IQ>::iew()
// memory access.
ldstQueue.insertLoad(inst);
+ ++iewDispLoadInsts;
} else if (inst->isStore()) {
ldstQueue.insertStore(inst);
@@ -327,10 +328,15 @@ SimpleIEW<Impl, IQ>::iew()
// the commit stage will try committing it, and then
// once commit realizes it's a store it will send back
// a signal to this stage to issue and execute that
- // store.
+ // store. Change to be a bit that says the instruction
+ // has extra work to do at commit.
inst->setCanCommit();
instQueue.insertNonSpec(inst);
+
+ ++iewDispStoreInsts;
+ ++iewDispNonSpecInsts;
+
continue;
} else if (inst->isNonSpeculative()) {
DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
@@ -342,6 +348,8 @@ SimpleIEW<Impl, IQ>::iew()
// Specificall insert it as nonspeculative.
instQueue.insertNonSpec(inst);
+ ++iewDispNonSpecInsts;
+
continue;
} else if (inst->isNop()) {
DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
@@ -352,25 +360,35 @@ SimpleIEW<Impl, IQ>::iew()
inst->setCanCommit();
instQueue.advanceTail(inst);
+
+ continue;
+ } else if (inst->isExecuted()) {
+ DPRINTF(IEW, "IEW: Issue: Executed branch encountered, "
+ "skipping.\n");
+
+ assert(inst->isDirectCtrl());
+
+ inst->setIssued();
+ inst->setCanCommit();
+
+ instQueue.advanceTail(inst);
+
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;
- break;
}
// If the instruction queue is not full, then add the
// instruction.
instQueue.insert(fromRename->insts[inst_num]);
+
+ ++iewDispatchedInsts;
}
}
+}
- // Have the instruction queue try to schedule any ready instructions.
- instQueue.scheduleReadyInsts();
-
+template <class Impl, class IQ>
+void
+SimpleIEW<Impl, IQ>::executeInsts()
+{
////////////////////////////////////////
//EXECUTE/WRITEBACK stage
////////////////////////////////////////
@@ -389,9 +407,10 @@ SimpleIEW<Impl, IQ>::iew()
// Execute/writeback any instructions that are available.
for (int inst_num = 0;
fu_usage < executeWidth && /* Haven't exceeded available FU's. */
- inst_num < issueWidth && /* Haven't exceeded issue width. */
- fromIssue->insts[inst_num]; /* There are available instructions. */
+ inst_num < issueWidth &&
+ fromIssue->insts[inst_num];
++inst_num) {
+
DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
// Get instruction from issue's queue.
@@ -410,6 +429,8 @@ SimpleIEW<Impl, IQ>::iew()
toCommit->insts[inst_num] = inst;
+ ++iewExecSquashedInsts;
+
continue;
}
@@ -428,14 +449,20 @@ SimpleIEW<Impl, IQ>::iew()
// 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();
+
+ ++iewExecStoreInsts;
} else {
panic("IEW: Unexpected memory type!\n");
}
} else {
inst->execute();
+
+ ++iewExecutedInsts;
}
// First check the time slot that this instruction will write
@@ -464,25 +491,148 @@ SimpleIEW<Impl, IQ>::iew()
inst->nextPC);
// If incorrect, then signal the ROB that it must be squashed.
- squash(inst);
+ 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(inst);
- // Otherwise check if there was a memory ordering violation.
- // If there was, then signal ROB that it must be squashed. Also
- // signal IQ that there was a violation.
+ // Squash.
+ squashDueToMem(inst);
+
+ ++memOrderViolationEvents;
}
}
}
+}
+
+template<class Impl, class IQ>
+void
+SimpleIEW<Impl, IQ>::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;
+
+ // Also should advance its own time buffers if the stage ran.
+ // Not sure about this...
+// issueToExecQueue.advance();
+ } 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();
+
+ // 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.
+ if (fromCommit->commitInfo.commitIsStore) {
+ ldstQueue.commitStores(fromCommit->commitInfo.doneSeqNum);
+ } else if (fromCommit->commitInfo.commitIsLoad) {
+ 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, class IQ>
+void
+SimpleIEW<Impl, IQ>::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
@@ -491,7 +641,7 @@ SimpleIEW<Impl, IQ>::iew()
// 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 < executeWidth &&
+ for (int inst_num = 0; inst_num < issueWidth &&
toCommit->insts[inst_num]; inst_num++)
{
DynInstPtr inst = toCommit->insts[inst_num];