#include "cpu/o3/iew.hh"
template<class Impl>
-DefaultIEW<Impl>::DefaultIEW(Params *params)
+DefaultIEW<Impl>::DefaultIEW(O3CPU *_cpu, Params *params)
: issueToExecQueue(params->backComSize, params->forwardComSize),
- instQueue(params),
- ldstQueue(params),
+ cpu(_cpu),
+ instQueue(_cpu, this, params),
+ ldstQueue(_cpu, this, params),
fuPool(params->fuPool),
commitToIEWDelay(params->commitToIEWDelay),
renameToIEWDelay(params->renameToIEWDelay),
// Instruction queue needs the queue between issue and execute.
instQueue.setIssueToExecuteQueue(&issueToExecQueue);
- instQueue.setIEW(this);
- ldstQueue.setIEW(this);
-
for (int i=0; i < numThreads; i++) {
dispatchStatus[i] = Running;
stalls[i].commit = false;
fetchRedirect[i] = false;
- bdelayDoneSeqNum[i] = 0;
}
wbMax = wbWidth * params->wbDepth;
toRename->iewInfo[tid].freeLSQEntries =
ldstQueue.numFreeEntries(tid);
}
-}
-
-template<class Impl>
-void
-DefaultIEW<Impl>::setCPU(O3CPU *cpu_ptr)
-{
- DPRINTF(IEW, "Setting CPU pointer.\n");
- cpu = cpu_ptr;
-
- instQueue.setCPU(cpu_ptr);
- ldstQueue.setCPU(cpu_ptr);
cpu->activateStage(O3CPU::IEWIdx);
}
void
DefaultIEW<Impl>::setTimeBuffer(TimeBuffer<TimeStruct> *tb_ptr)
{
- DPRINTF(IEW, "Setting time buffer pointer.\n");
timeBuffer = tb_ptr;
// Setup wire to read information from time buffer, from commit.
void
DefaultIEW<Impl>::setRenameQueue(TimeBuffer<RenameStruct> *rq_ptr)
{
- DPRINTF(IEW, "Setting rename queue pointer.\n");
renameQueue = rq_ptr;
// Setup wire to read information from rename queue.
void
DefaultIEW<Impl>::setIEWQueue(TimeBuffer<IEWStruct> *iq_ptr)
{
- DPRINTF(IEW, "Setting IEW queue pointer.\n");
iewQueue = iq_ptr;
// Setup wire to write instructions to commit.
void
DefaultIEW<Impl>::setActiveThreads(std::list<unsigned> *at_ptr)
{
- DPRINTF(IEW, "Setting active threads list pointer.\n");
activeThreads = at_ptr;
ldstQueue.setActiveThreads(at_ptr);
void
DefaultIEW<Impl>::setScoreboard(Scoreboard *sb_ptr)
{
- DPRINTF(IEW, "Setting scoreboard pointer.\n");
scoreboard = sb_ptr;
}
instQueue.squash(tid);
// Tell the LDSTQ to start squashing.
-#if ISA_HAS_DELAY_SLOT
- ldstQueue.squash(fromCommit->commitInfo[tid].bdelayDoneSeqNum, tid);
-#else
ldstQueue.squash(fromCommit->commitInfo[tid].doneSeqNum, tid);
-#endif
updatedQueues = true;
// Clear the skid buffer in case it has any data in it.
DPRINTF(IEW, "[tid:%i]: Removing skidbuffer instructions until [sn:%i].\n",
- tid, fromCommit->commitInfo[tid].bdelayDoneSeqNum);
+ tid, fromCommit->commitInfo[tid].doneSeqNum);
while (!skidBuffer[tid].empty()) {
-#if ISA_HAS_DELAY_SLOT
- if (skidBuffer[tid].front()->seqNum <=
- fromCommit->commitInfo[tid].bdelayDoneSeqNum) {
- DPRINTF(IEW, "[tid:%i]: Cannot remove skidbuffer instructions "
- "that occur before delay slot [sn:%i].\n",
- fromCommit->commitInfo[tid].bdelayDoneSeqNum,
- tid);
- break;
- } else {
- DPRINTF(IEW, "[tid:%i]: Removing instruction [sn:%i] from "
- "skidBuffer.\n", tid, skidBuffer[tid].front()->seqNum);
- }
-#endif
if (skidBuffer[tid].front()->isLoad() ||
skidBuffer[tid].front()->isStore() ) {
toRename->iewInfo[tid].dispatchedToLSQ++;
skidBuffer[tid].pop();
}
- bdelayDoneSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum;
-
emptyRenameInsts(tid);
}
toCommit->branchMispredict[tid] = true;
#if ISA_HAS_DELAY_SLOT
- bool branch_taken = inst->readNextNPC() !=
- (inst->readNextPC() + sizeof(TheISA::MachInst));
-
- toCommit->branchTaken[tid] = branch_taken;
-
- toCommit->condDelaySlotBranch[tid] = inst->isCondDelaySlot();
-
- if (inst->isCondDelaySlot() && branch_taken) {
- toCommit->nextPC[tid] = inst->readNextPC();
- } else {
- toCommit->nextPC[tid] = inst->readNextNPC();
- }
+ int instSize = sizeof(TheISA::MachInst);
+ toCommit->branchTaken[tid] =
+ !(inst->readNextPC() + instSize == inst->readNextNPC() &&
+ (inst->readNextPC() == inst->readPC() + instSize ||
+ inst->readNextPC() == inst->readPC() + 2 * instSize));
#else
toCommit->branchTaken[tid] = inst->readNextPC() !=
(inst->readPC() + sizeof(TheISA::MachInst));
- toCommit->nextPC[tid] = inst->readNextPC();
#endif
+ toCommit->nextPC[tid] = inst->readNextPC();
+ toCommit->nextNPC[tid] = inst->readNextNPC();
+ toCommit->nextMicroPC[tid] = inst->readNextMicroPC();
toCommit->includeSquashInst[tid] = false;
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
toCommit->nextPC[tid] = inst->readNextPC();
+ toCommit->nextNPC[tid] = inst->readNextNPC();
+ toCommit->branchMispredict[tid] = false;
toCommit->includeSquashInst[tid] = false;
toCommit->squash[tid] = true;
toCommit->squashedSeqNum[tid] = inst->seqNum;
toCommit->nextPC[tid] = inst->readPC();
+ toCommit->nextNPC[tid] = inst->readNextPC();
+ toCommit->branchMispredict[tid] = false;
// Must include the broadcasted SN in the squash.
toCommit->includeSquashInst[tid] = true;
{
int max=0;
- std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = activeThreads->begin();
+ std::list<unsigned>::iterator end = activeThreads->end();
- while (threads != (*activeThreads).end()) {
- unsigned thread_count = skidBuffer[*threads++].size();
+ while (threads != end) {
+ unsigned tid = *threads++;
+ unsigned thread_count = skidBuffer[tid].size();
if (max < thread_count)
max = thread_count;
}
bool
DefaultIEW<Impl>::skidsEmpty()
{
- std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = activeThreads->begin();
+ std::list<unsigned>::iterator end = activeThreads->end();
- while (threads != (*activeThreads).end()) {
- if (!skidBuffer[*threads++].empty())
+ while (threads != end) {
+ unsigned tid = *threads++;
+
+ if (!skidBuffer[tid].empty())
return false;
}
{
bool any_unblocking = false;
- std::list<unsigned>::iterator threads = (*activeThreads).begin();
-
- threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = activeThreads->begin();
+ std::list<unsigned>::iterator end = activeThreads->end();
- while (threads != (*activeThreads).end()) {
+ while (threads != end) {
unsigned tid = *threads++;
if (dispatchStatus[tid] == Unblocking) {
{
int insts_from_rename = fromRename->size;
#ifdef DEBUG
-#if !ISA_HAS_DELAY_SLOT
for (int i = 0; i < numThreads; i++)
assert(insts[i].empty());
-#endif
#endif
for (int i = 0; i < insts_from_rename; ++i) {
insts[fromRename->insts[i]->threadNumber].push(fromRename->insts[i]);
void
DefaultIEW<Impl>::emptyRenameInsts(unsigned tid)
{
- DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions until "
- "[sn:%i].\n", tid, bdelayDoneSeqNum[tid]);
+ DPRINTF(IEW, "[tid:%i]: Removing incoming rename instructions\n", tid);
while (!insts[tid].empty()) {
-#if ISA_HAS_DELAY_SLOT
- if (insts[tid].front()->seqNum <= bdelayDoneSeqNum[tid]) {
- DPRINTF(IEW, "[tid:%i]: Done removing, cannot remove instruction"
- " that occurs at or before delay slot [sn:%i].\n",
- tid, bdelayDoneSeqNum[tid]);
- break;
- } else {
- DPRINTF(IEW, "[tid:%i]: Removing incoming rename instruction "
- "[sn:%i].\n", tid, insts[tid].front()->seqNum);
- }
-#endif
if (insts[tid].front()->isLoad() ||
insts[tid].front()->isStore() ) {
}
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);
-
- // Same as non-speculative stores.
- inst->setCanCommit();
-
- // Specifically insert it as nonspeculative.
- instQueue.insertNonSpec(inst);
-
- ++iewDispNonSpecInsts;
-
add_to_iq = false;
} else if (inst->isNop()) {
DPRINTF(IEW, "[tid:%i]: Issue: Nop instruction encountered, "
} else {
add_to_iq = true;
}
+ if (inst->isNonSpeculative()) {
+ DPRINTF(IEW, "[tid:%i]: Issue: Nonspeculative instruction "
+ "encountered, skipping.\n", tid);
+
+ // Same as non-speculative stores.
+ inst->setCanCommit();
+
+ // Specifically insert it as nonspeculative.
+ instQueue.insertNonSpec(inst);
+
+ ++iewDispNonSpecInsts;
+
+ add_to_iq = false;
+ }
// If the instruction queue is not full, then add the
// instruction.
wbNumInst = 0;
wbCycle = 0;
- std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = activeThreads->begin();
+ std::list<unsigned>::iterator end = activeThreads->end();
- while (threads != (*activeThreads).end()) {
+ while (threads != end) {
unsigned tid = *threads++;
fetchRedirect[tid] = false;
}
} else if (fault != NoFault) {
// If the instruction faulted, then we need to send it along to commit
// without the instruction completing.
- DPRINTF(IEW, "Store has fault! [sn:%lli]\n", inst->seqNum);
+ DPRINTF(IEW, "Store has fault %s! [sn:%lli]\n",
+ fault->name(), inst->seqNum);
// Send this instruction to commit, also make sure iew stage
// realizes there is activity.
// instruction first, so the branch resolution order will be correct.
unsigned tid = inst->threadNumber;
- if (!fetchRedirect[tid]) {
+ if (!fetchRedirect[tid] ||
+ toCommit->squashedSeqNum[tid] > inst->seqNum) {
if (inst->mispredicted()) {
fetchRedirect[tid] = true;
DPRINTF(IEW, "Execute: Branch mispredict detected.\n");
-#if ISA_HAS_DELAY_SLOT
- DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextNPC);
-#else
- DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x.\n",
- inst->nextPC);
-#endif
+ DPRINTF(IEW, "Predicted target was %#x, %#x.\n",
+ inst->readPredPC(), inst->readPredNPC());
+ DPRINTF(IEW, "Execute: Redirecting fetch to PC: %#x,"
+ " NPC: %#x.\n", inst->readNextPC(),
+ inst->readNextNPC());
// If incorrect, then signal the ROB that it must be squashed.
squashDueToBranch(inst, tid);
- if (inst->predTaken()) {
+ if (inst->readPredTaken()) {
predictedTakenIncorrect++;
} else {
predictedNotTakenIncorrect++;
}
} else if (ldstQueue.violation(tid)) {
- fetchRedirect[tid] = true;
-
+ assert(inst->isMemRef());
// If there was an ordering violation, then get the
// DynInst that caused the violation. Note that this
// clears the violation signal.
"%#x, inst PC: %#x. Addr is: %#x.\n",
violator->readPC(), inst->readPC(), inst->physEffAddr);
+ // Ensure the violating instruction is older than
+ // current squash
+/* if (fetchRedirect[tid] &&
+ violator->seqNum >= toCommit->squashedSeqNum[tid] + 1)
+ continue;
+*/
+ fetchRedirect[tid] = true;
+
// Tell the instruction queue that a violation has occured.
instQueue.violation(inst, violator);
squashDueToMemBlocked(inst, tid);
}
+ } else {
+ // Reset any state associated with redirects that will not
+ // be used.
+ if (ldstQueue.violation(tid)) {
+ assert(inst->isMemRef());
+
+ DynInstPtr violator = ldstQueue.getMemDepViolator(tid);
+
+ DPRINTF(IEW, "LDSTQ detected a violation. Violator PC: "
+ "%#x, inst PC: %#x. Addr is: %#x.\n",
+ violator->readPC(), inst->readPC(), inst->physEffAddr);
+ DPRINTF(IEW, "Violation will not be handled because "
+ "already squashing\n");
+
+ ++memOrderViolationEvents;
+ }
+ if (ldstQueue.loadBlocked(tid) &&
+ !ldstQueue.isLoadBlockedHandled(tid)) {
+ DPRINTF(IEW, "Load operation couldn't execute because the "
+ "memory system is blocked. PC: %#x [sn:%lli]\n",
+ inst->readPC(), inst->seqNum);
+ DPRINTF(IEW, "Blocked load will not be handled because "
+ "already squashing\n");
+
+ ldstQueue.setLoadBlockedHandled(tid);
+ }
+
}
}
// 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 &&
+ for (int inst_num = 0; inst_num < wbWidth &&
toCommit->insts[inst_num]; inst_num++) {
DynInstPtr inst = toCommit->insts[inst_num];
int tid = inst->threadNumber;
// Free function units marked as being freed this cycle.
fuPool->processFreeUnits();
- std::list<unsigned>::iterator threads = (*activeThreads).begin();
+ std::list<unsigned>::iterator threads = activeThreads->begin();
+ std::list<unsigned>::iterator end = activeThreads->end();
// Check stall and squash signals, dispatch any instructions.
- while (threads != (*activeThreads).end()) {
- unsigned tid = *threads++;
+ while (threads != end) {
+ unsigned tid = *threads++;
DPRINTF(IEW,"Issue: Processing [tid:%i]\n",tid);
// nonspeculative instruction.
// This is pretty inefficient...
- threads = (*activeThreads).begin();
- while (threads != (*activeThreads).end()) {
+ threads = activeThreads->begin();
+ while (threads != end) {
unsigned tid = (*threads++);
DPRINTF(IEW,"Processing [tid:%i]\n",tid);
//DPRINTF(IEW,"NonspecInst from thread %i",tid);
if (fromCommit->commitInfo[tid].uncached) {
instQueue.replayMemInst(fromCommit->commitInfo[tid].uncachedLoad);
+ fromCommit->commitInfo[tid].uncachedLoad->setAtCommit();
} else {
instQueue.scheduleNonSpec(
fromCommit->commitInfo[tid].nonSpecSeqNum);