X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Fo3%2Fiew_impl.hh;h=399c449092d708403adc5d4e3bffcfa141e931d0;hb=142362b703e666f82c6b1f57e2d729e0641be166;hp=ba5260fe209c99e99b3be34f9d19da63100bf20e;hpb=3a9eb598c3e71b543ba9b8fda42b76c89a645634;p=gem5.git diff --git a/src/cpu/o3/iew_impl.hh b/src/cpu/o3/iew_impl.hh index ba5260fe2..399c44909 100644 --- a/src/cpu/o3/iew_impl.hh +++ b/src/cpu/o3/iew_impl.hh @@ -39,10 +39,11 @@ #include "cpu/o3/iew.hh" template -DefaultIEW::DefaultIEW(Params *params) +DefaultIEW::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), @@ -64,14 +65,10 @@ DefaultIEW::DefaultIEW(Params *params) // 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; @@ -276,17 +273,6 @@ DefaultIEW::initStage() toRename->iewInfo[tid].freeLSQEntries = ldstQueue.numFreeEntries(tid); } -} - -template -void -DefaultIEW::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); } @@ -295,7 +281,6 @@ template void DefaultIEW::setTimeBuffer(TimeBuffer *tb_ptr) { - DPRINTF(IEW, "Setting time buffer pointer.\n"); timeBuffer = tb_ptr; // Setup wire to read information from time buffer, from commit. @@ -314,7 +299,6 @@ template void DefaultIEW::setRenameQueue(TimeBuffer *rq_ptr) { - DPRINTF(IEW, "Setting rename queue pointer.\n"); renameQueue = rq_ptr; // Setup wire to read information from rename queue. @@ -325,7 +309,6 @@ template void DefaultIEW::setIEWQueue(TimeBuffer *iq_ptr) { - DPRINTF(IEW, "Setting IEW queue pointer.\n"); iewQueue = iq_ptr; // Setup wire to write instructions to commit. @@ -336,7 +319,6 @@ template void DefaultIEW::setActiveThreads(std::list *at_ptr) { - DPRINTF(IEW, "Setting active threads list pointer.\n"); activeThreads = at_ptr; ldstQueue.setActiveThreads(at_ptr); @@ -347,7 +329,6 @@ template void DefaultIEW::setScoreboard(Scoreboard *sb_ptr) { - DPRINTF(IEW, "Setting scoreboard pointer.\n"); scoreboard = sb_ptr; } @@ -428,31 +409,14 @@ DefaultIEW::squash(unsigned tid) 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++; @@ -463,8 +427,6 @@ DefaultIEW::squash(unsigned tid) skidBuffer[tid].pop(); } - bdelayDoneSeqNum[tid] = fromCommit->commitInfo[tid].bdelayDoneSeqNum; - emptyRenameInsts(tid); } @@ -481,23 +443,18 @@ DefaultIEW::squashDueToBranch(DynInstPtr &inst, unsigned 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; @@ -514,6 +471,8 @@ DefaultIEW::squashDueToMemOrder(DynInstPtr &inst, unsigned tid) 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; @@ -530,6 +489,8 @@ DefaultIEW::squashDueToMemBlocked(DynInstPtr &inst, unsigned tid) 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; @@ -669,10 +630,12 @@ DefaultIEW::skidCount() { int max=0; - std::list::iterator threads = (*activeThreads).begin(); + std::list::iterator threads = activeThreads->begin(); + std::list::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; } @@ -684,10 +647,13 @@ template bool DefaultIEW::skidsEmpty() { - std::list::iterator threads = (*activeThreads).begin(); + std::list::iterator threads = activeThreads->begin(); + std::list::iterator end = activeThreads->end(); - while (threads != (*activeThreads).end()) { - if (!skidBuffer[*threads++].empty()) + while (threads != end) { + unsigned tid = *threads++; + + if (!skidBuffer[tid].empty()) return false; } @@ -700,11 +666,10 @@ DefaultIEW::updateStatus() { bool any_unblocking = false; - std::list::iterator threads = (*activeThreads).begin(); - - threads = (*activeThreads).begin(); + std::list::iterator threads = activeThreads->begin(); + std::list::iterator end = activeThreads->end(); - while (threads != (*activeThreads).end()) { + while (threads != end) { unsigned tid = *threads++; if (dispatchStatus[tid] == Unblocking) { @@ -868,10 +833,8 @@ DefaultIEW::sortInsts() { 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]); @@ -882,21 +845,9 @@ template void DefaultIEW::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() ) { @@ -1118,25 +1069,10 @@ DefaultIEW::dispatchInsts(unsigned tid) } 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, " @@ -1165,6 +1101,20 @@ DefaultIEW::dispatchInsts(unsigned tid) } 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. @@ -1224,9 +1174,10 @@ DefaultIEW::executeInsts() wbNumInst = 0; wbCycle = 0; - std::list::iterator threads = (*activeThreads).begin(); + std::list::iterator threads = activeThreads->begin(); + std::list::iterator end = activeThreads->end(); - while (threads != (*activeThreads).end()) { + while (threads != end) { unsigned tid = *threads++; fetchRedirect[tid] = false; } @@ -1291,7 +1242,8 @@ DefaultIEW::executeInsts() } 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. @@ -1328,30 +1280,28 @@ DefaultIEW::executeInsts() // 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. @@ -1362,6 +1312,14 @@ DefaultIEW::executeInsts() "%#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); @@ -1379,6 +1337,33 @@ DefaultIEW::executeInsts() 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); + } + } } @@ -1408,7 +1393,7 @@ DefaultIEW::writebackInsts() // 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; @@ -1459,11 +1444,12 @@ DefaultIEW::tick() // Free function units marked as being freed this cycle. fuPool->processFreeUnits(); - std::list::iterator threads = (*activeThreads).begin(); + std::list::iterator threads = activeThreads->begin(); + std::list::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); @@ -1503,8 +1489,8 @@ DefaultIEW::tick() // 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); @@ -1527,6 +1513,7 @@ DefaultIEW::tick() //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);