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.hh156
1 files changed, 114 insertions, 42 deletions
diff --git a/cpu/beta_cpu/iew_impl.hh b/cpu/beta_cpu/iew_impl.hh
index b198220f5..521ce77f6 100644
--- a/cpu/beta_cpu/iew_impl.hh
+++ b/cpu/beta_cpu/iew_impl.hh
@@ -3,8 +3,8 @@
// communication happens simultaneously. Might not be that bad really...
// it might skew stats a bit though. Issue would otherwise try to issue
// instructions that would never be executed if there were a delay; without
-// it issue will simply squash. Make this stage block properly. Make this
-// stage delay after a squash properly. Update the statuses for each stage.
+// it issue will simply squash. Make this stage block properly.
+// Update the statuses for each stage.
// Actually read instructions out of the skid buffer.
#include <queue>
@@ -15,8 +15,9 @@
template<class Impl, class IQ>
SimpleIEW<Impl, IQ>::SimpleIEW(Params &params)
: // Just make this time buffer really big for now
- issueToExecQueue(20, 20),
+ issueToExecQueue(5, 5),
instQueue(params),
+ ldstQueue(params),
commitToIEWDelay(params.commitToIEWDelay),
renameToIEWDelay(params.renameToIEWDelay),
issueToExecuteDelay(params.issueToExecuteDelay),
@@ -45,6 +46,7 @@ SimpleIEW<Impl, IQ>::setCPU(FullCPU *cpu_ptr)
cpu = cpu_ptr;
instQueue.setCPU(cpu_ptr);
+ ldstQueue.setCPU(cpu_ptr);
}
template<class Impl, class IQ>
@@ -96,7 +98,7 @@ SimpleIEW<Impl, IQ>::setRenameMap(RenameMap *rm_ptr)
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::wakeDependents(DynInst *inst)
+SimpleIEW<Impl, IQ>::wakeDependents(DynInstPtr &inst)
{
instQueue.wakeDependents(inst);
}
@@ -150,17 +152,15 @@ SimpleIEW<Impl, IQ>::squash()
// Tell the IQ to start squashing.
instQueue.squash();
- // Tell rename to squash through the time buffer.
- // This communication may be redundant depending upon where squash()
- // is called.
-// toRename->iewInfo.squash = true;
+ // Tell the LDSTQ to start squashing.
+ ldstQueue.squash(fromCommit->commitInfo.doneSeqNum);
}
template<class Impl, class IQ>
void
-SimpleIEW<Impl, IQ>::squash(DynInst *inst)
+SimpleIEW<Impl, IQ>::squash(DynInstPtr &inst)
{
- DPRINTF(IEW, "IEW: Squashing from a specific instruction, PC:%#x.\n",
+ 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?
@@ -170,8 +170,11 @@ SimpleIEW<Impl, IQ>::squash(DynInst *inst)
toRename->iewInfo.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.predIncorrect = true;
+ toRename->iewInfo.branchMispredict = true;
+ // Prediction was incorrect, so send back inverse.
+ toRename->iewInfo.branchTaken = !(inst->predTaken());
}
template<class Impl, class IQ>
@@ -229,7 +232,7 @@ SimpleIEW<Impl, IQ>::tick()
// If there's still instructions coming from rename, continue to
// put them on the skid buffer.
- if (fromRename->insts[0] != NULL) {
+ if (fromRename->insts[0]) {
block();
}
@@ -244,6 +247,19 @@ SimpleIEW<Impl, IQ>::tick()
// 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());
}
@@ -265,7 +281,7 @@ SimpleIEW<Impl, IQ>::iew()
}
////////////////////////////////////////
- //ISSUE stage
+ // DISPATCH/ISSUE stage
////////////////////////////////////////
//Put into its own function?
@@ -273,16 +289,16 @@ SimpleIEW<Impl, IQ>::iew()
// Check if there are any instructions coming from rename, and we're.
// not squashing.
- if (fromRename->insts[0] != NULL && _status != Squashing) {
+ if (fromRename->insts[0] && _status != Squashing) {
// Loop through the instructions, putting them in the instruction
// queue.
for (int inst_num = 0; inst_num < issueReadWidth; ++inst_num)
{
- DynInst *inst = fromRename->insts[inst_num];
+ DynInstPtr inst = fromRename->insts[inst_num];
// Make sure there's a valid instruction there.
- if (inst == NULL)
+ if (!inst)
break;
DPRINTF(IEW, "IEW: Issue: Adding PC %#x to IQ.\n",
@@ -294,25 +310,38 @@ SimpleIEW<Impl, IQ>::iew()
// 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->isMemRef()) {
+ if (inst->isSquashed()) {
+ continue;
+ } else if (inst->isLoad()) {
DPRINTF(IEW, "IEW: Issue: Memory instruction "
- "encountered, skipping.\n");
+ "encountered, adding to LDSTQ.\n");
- inst->setIssued();
- inst->setExecuted();
+ // Reserve a spot in the load store queue for this
+ // memory access.
+ ldstQueue.insertLoad(inst);
+
+ } else if (inst->isStore()) {
+ ldstQueue.insertStore(inst);
+
+ // A bit of a hack. Set that it can commit so that
+ // 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.
inst->setCanCommit();
- instQueue.advanceTail(inst);
+ instQueue.insertNonSpec(inst);
continue;
} else if (inst->isNonSpeculative()) {
DPRINTF(IEW, "IEW: Issue: Nonspeculative instruction "
"encountered, skipping.\n");
- inst->setIssued();
- inst->setExecuted();
+ // Same hack as with stores.
inst->setCanCommit();
- instQueue.advanceTail(inst);
+ // Specificall insert it as nonspeculative.
+ instQueue.insertNonSpec(inst);
+
continue;
} else if (inst->isNop()) {
DPRINTF(IEW, "IEW: Issue: Nop instruction encountered "
@@ -355,6 +384,7 @@ SimpleIEW<Impl, IQ>::iew()
// @todo: Move to the FU pool used in the current full cpu.
int fu_usage = 0;
+ bool fetch_redirect = false;
// Execute/writeback any instructions that are available.
for (int inst_num = 0;
@@ -365,26 +395,48 @@ SimpleIEW<Impl, IQ>::iew()
DPRINTF(IEW, "IEW: Execute: Executing instructions from IQ.\n");
// Get instruction from issue's queue.
- DynInst *inst = fromIssue->insts[inst_num];
+ DynInstPtr inst = fromIssue->insts[inst_num];
DPRINTF(IEW, "IEW: Execute: Processing PC %#x.\n", inst->readPC());
- inst->setExecuted();
-
// 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;
+
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.
- inst->execute();
+ 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);
+ } else if (inst->isStore()) {
+ ldstQueue.executeStore();
+ } else {
+ panic("IEW: Unexpected memory type!\n");
+ }
+
+ } else {
+ inst->execute();
+ }
// First check the time slot that this instruction will write
// to. If there are free write ports at the time, then go ahead
@@ -401,16 +453,34 @@ SimpleIEW<Impl, IQ>::iew()
// 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.
- if (inst->mispredicted()) {
- DPRINTF(IEW, "IEW: Execute: Branch mispredict detected.\n");
- DPRINTF(IEW, "IEW: Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextPC);
+ // 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.
+ squash(inst);
+ } else if (ldstQueue.violation()) {
+ fetch_redirect = true;
+
+ DynInstPtr violator = ldstQueue.getMemDepViolator();
- // If incorrect, then signal the ROB that it must be squashed.
- squash(inst);
+ DPRINTF(IEW, "IEW: LDSTQ detected a violation. Violator PC: "
+ "%#x, inst PC: %#x. Addr is: %#x.\n",
+ violator->readPC(), inst->readPC(), inst->physEffAddr);
- // Not sure it really needs to break.
-// break;
+ 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.
+ }
}
}
@@ -422,18 +492,20 @@ SimpleIEW<Impl, IQ>::iew()
// 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 &&
- toCommit->insts[inst_num] != NULL; inst_num++)
+ toCommit->insts[inst_num]; inst_num++)
{
- DynInst *inst = toCommit->insts[inst_num];
+ DynInstPtr inst = toCommit->insts[inst_num];
DPRINTF(IEW, "IEW: Sending instructions to commit, PC %#x.\n",
inst->readPC());
- instQueue.wakeDependents(inst);
+ if(!inst->isSquashed()) {
+ instQueue.wakeDependents(inst);
- for (int i = 0; i < inst->numDestRegs(); i++)
- {
- renameMap->markAsReady(inst->renamedDestRegIdx(i));
+ for (int i = 0; i < inst->numDestRegs(); i++)
+ {
+ renameMap->markAsReady(inst->renamedDestRegIdx(i));
+ }
}
}