X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcpu%2Fo3%2Fdecode_impl.hh;h=a523a8b45129801f2c3455e03c463e7b47d247db;hb=525d1e46dcb3180c8d73996adc025ce255575bd7;hp=8b851c032810327f4fb8f3f0aa0891dacb55f404;hpb=b2a479cfc89e3109830bd285b0819b6a0b56cbf4;p=gem5.git diff --git a/src/cpu/o3/decode_impl.hh b/src/cpu/o3/decode_impl.hh index 8b851c032..a523a8b45 100644 --- a/src/cpu/o3/decode_impl.hh +++ b/src/cpu/o3/decode_impl.hh @@ -28,28 +28,37 @@ * Authors: Kevin Lim */ +#include "arch/types.hh" +#include "base/trace.hh" +#include "config/full_system.hh" +#include "config/the_isa.hh" #include "cpu/o3/decode.hh" +#include "cpu/inst_seq.hh" +#include "debug/Activity.hh" +#include "debug/Decode.hh" +#include "params/DerivO3CPU.hh" using namespace std; template -DefaultDecode::DefaultDecode(Params *params) - : renameToDecodeDelay(params->renameToDecodeDelay), +DefaultDecode::DefaultDecode(O3CPU *_cpu, DerivO3CPUParams *params) + : cpu(_cpu), + renameToDecodeDelay(params->renameToDecodeDelay), iewToDecodeDelay(params->iewToDecodeDelay), commitToDecodeDelay(params->commitToDecodeDelay), fetchToDecodeDelay(params->fetchToDecodeDelay), decodeWidth(params->decodeWidth), - numThreads(params->numberOfThreads) + numThreads(params->numThreads) { _status = Inactive; // Setup status, make sure stall signals are clear. - for (int i = 0; i < numThreads; ++i) { - decodeStatus[i] = Idle; + for (ThreadID tid = 0; tid < numThreads; ++tid) { + decodeStatus[tid] = Idle; - stalls[i].rename = false; - stalls[i].iew = false; - stalls[i].commit = false; + stalls[tid].rename = false; + stalls[tid].iew = false; + stalls[tid].commit = false; } // @todo: Make into a parameter @@ -68,61 +77,52 @@ void DefaultDecode::regStats() { decodeIdleCycles - .name(name() + ".DECODE:IdleCycles") + .name(name() + ".IdleCycles") .desc("Number of cycles decode is idle") .prereq(decodeIdleCycles); decodeBlockedCycles - .name(name() + ".DECODE:BlockedCycles") + .name(name() + ".BlockedCycles") .desc("Number of cycles decode is blocked") .prereq(decodeBlockedCycles); decodeRunCycles - .name(name() + ".DECODE:RunCycles") + .name(name() + ".RunCycles") .desc("Number of cycles decode is running") .prereq(decodeRunCycles); decodeUnblockCycles - .name(name() + ".DECODE:UnblockCycles") + .name(name() + ".UnblockCycles") .desc("Number of cycles decode is unblocking") .prereq(decodeUnblockCycles); decodeSquashCycles - .name(name() + ".DECODE:SquashCycles") + .name(name() + ".SquashCycles") .desc("Number of cycles decode is squashing") .prereq(decodeSquashCycles); decodeBranchResolved - .name(name() + ".DECODE:BranchResolved") + .name(name() + ".BranchResolved") .desc("Number of times decode resolved a branch") .prereq(decodeBranchResolved); decodeBranchMispred - .name(name() + ".DECODE:BranchMispred") + .name(name() + ".BranchMispred") .desc("Number of times decode detected a branch misprediction") .prereq(decodeBranchMispred); decodeControlMispred - .name(name() + ".DECODE:ControlMispred") + .name(name() + ".ControlMispred") .desc("Number of times decode detected an instruction incorrectly" " predicted as a control") .prereq(decodeControlMispred); decodeDecodedInsts - .name(name() + ".DECODE:DecodedInsts") + .name(name() + ".DecodedInsts") .desc("Number of instructions handled by decode") .prereq(decodeDecodedInsts); decodeSquashedInsts - .name(name() + ".DECODE:SquashedInsts") + .name(name() + ".SquashedInsts") .desc("Number of squashed instructions handled by decode") .prereq(decodeSquashedInsts); } -template -void -DefaultDecode::setCPU(O3CPU *cpu_ptr) -{ - DPRINTF(Decode, "Setting CPU pointer.\n"); - cpu = cpu_ptr; -} - template void DefaultDecode::setTimeBuffer(TimeBuffer *tb_ptr) { - DPRINTF(Decode, "Setting time buffer pointer.\n"); timeBuffer = tb_ptr; // Setup wire to write information back to fetch. @@ -138,7 +138,6 @@ template void DefaultDecode::setDecodeQueue(TimeBuffer *dq_ptr) { - DPRINTF(Decode, "Setting decode queue pointer.\n"); decodeQueue = dq_ptr; // Setup wire to write information to proper place in decode queue. @@ -149,7 +148,6 @@ template void DefaultDecode::setFetchQueue(TimeBuffer *fq_ptr) { - DPRINTF(Decode, "Setting fetch queue pointer.\n"); fetchQueue = fq_ptr; // Setup wire to read information from fetch queue. @@ -158,9 +156,8 @@ DefaultDecode::setFetchQueue(TimeBuffer *fq_ptr) template void -DefaultDecode::setActiveThreads(list *at_ptr) +DefaultDecode::setActiveThreads(std::list *at_ptr) { - DPRINTF(Decode, "Setting active threads list pointer.\n"); activeThreads = at_ptr; } @@ -180,24 +177,24 @@ DefaultDecode::takeOverFrom() _status = Inactive; // Be sure to reset state and clear out any old instructions. - for (int i = 0; i < numThreads; ++i) { - decodeStatus[i] = Idle; - - stalls[i].rename = false; - stalls[i].iew = false; - stalls[i].commit = false; - while (!insts[i].empty()) - insts[i].pop(); - while (!skidBuffer[i].empty()) - skidBuffer[i].pop(); - branchCount[i] = 0; + for (ThreadID tid = 0; tid < numThreads; ++tid) { + decodeStatus[tid] = Idle; + + stalls[tid].rename = false; + stalls[tid].iew = false; + stalls[tid].commit = false; + while (!insts[tid].empty()) + insts[tid].pop(); + while (!skidBuffer[tid].empty()) + skidBuffer[tid].pop(); + branchCount[tid] = 0; } wroteToTimeBuffer = false; } template bool -DefaultDecode::checkStall(unsigned tid) const +DefaultDecode::checkStall(ThreadID tid) const { bool ret_val = false; @@ -224,7 +221,7 @@ DefaultDecode::fetchInstsValid() template bool -DefaultDecode::block(unsigned tid) +DefaultDecode::block(ThreadID tid) { DPRINTF(Decode, "[tid:%u]: Blocking.\n", tid); @@ -252,7 +249,7 @@ DefaultDecode::block(unsigned tid) template bool -DefaultDecode::unblock(unsigned tid) +DefaultDecode::unblock(ThreadID tid) { // Decode is done unblocking only if the skid buffer is empty. if (skidBuffer[tid].empty()) { @@ -271,19 +268,21 @@ DefaultDecode::unblock(unsigned tid) template void -DefaultDecode::squash(DynInstPtr &inst, unsigned tid) +DefaultDecode::squash(DynInstPtr &inst, ThreadID tid) { - DPRINTF(Decode, "[tid:%i]: Squashing due to incorrect branch prediction " - "detected at decode.\n", tid); + DPRINTF(Decode, "[tid:%i]: [sn:%i] Squashing due to incorrect branch " + "prediction detected at decode.\n", tid, inst->seqNum); // Send back mispredict information. toFetch->decodeInfo[tid].branchMispredict = true; - toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; toFetch->decodeInfo[tid].predIncorrect = true; toFetch->decodeInfo[tid].squash = true; + toFetch->decodeInfo[tid].doneSeqNum = inst->seqNum; toFetch->decodeInfo[tid].nextPC = inst->branchTarget(); - toFetch->decodeInfo[tid].branchTaken = - inst->readNextPC() != (inst->readPC() + sizeof(TheISA::MachInst)); + toFetch->decodeInfo[tid].branchTaken = inst->pcState().branching(); + toFetch->decodeInfo[tid].squashInst = inst; + + InstSeqNum squash_seq_num = inst->seqNum; // Might have to tell fetch to unblock. if (decodeStatus[tid] == Blocked || @@ -296,7 +295,7 @@ DefaultDecode::squash(DynInstPtr &inst, unsigned tid) for (int i=0; isize; i++) { if (fromFetch->insts[i]->threadNumber == tid && - fromFetch->insts[i]->seqNum > inst->seqNum) { + fromFetch->insts[i]->seqNum > squash_seq_num) { fromFetch->insts[i]->setSquashed(); } } @@ -312,12 +311,12 @@ DefaultDecode::squash(DynInstPtr &inst, unsigned tid) } // Squash instructions up until this one - cpu->removeInstsUntil(inst->seqNum, tid); + cpu->removeInstsUntil(squash_seq_num, tid); } template unsigned -DefaultDecode::squash(unsigned tid) +DefaultDecode::squash(ThreadID tid) { DPRINTF(Decode, "[tid:%i]: Squashing.\n",tid); @@ -366,7 +365,7 @@ DefaultDecode::squash(unsigned tid) template void -DefaultDecode::skidInsert(unsigned tid) +DefaultDecode::skidInsert(ThreadID tid) { DynInstPtr inst = NULL; @@ -377,8 +376,8 @@ DefaultDecode::skidInsert(unsigned tid) assert(tid == inst->threadNumber); - DPRINTF(Decode,"Inserting [sn:%lli] PC:%#x into decode skidBuffer %i\n", - inst->seqNum, inst->readPC(), inst->threadNumber); + DPRINTF(Decode,"Inserting [sn:%lli] PC: %s into decode skidBuffer %i\n", + inst->seqNum, inst->pcState(), inst->threadNumber); skidBuffer[tid].push(inst); } @@ -392,10 +391,12 @@ template bool DefaultDecode::skidsEmpty() { - list::iterator threads = (*activeThreads).begin(); + list::iterator threads = activeThreads->begin(); + list::iterator end = activeThreads->end(); - while (threads != (*activeThreads).end()) { - if (!skidBuffer[*threads++].empty()) + while (threads != end) { + ThreadID tid = *threads++; + if (!skidBuffer[tid].empty()) return false; } @@ -408,12 +409,11 @@ DefaultDecode::updateStatus() { bool any_unblocking = false; - list::iterator threads = (*activeThreads).begin(); + list::iterator threads = activeThreads->begin(); + list::iterator end = activeThreads->end(); - threads = (*activeThreads).begin(); - - while (threads != (*activeThreads).end()) { - unsigned tid = *threads++; + while (threads != end) { + ThreadID tid = *threads++; if (decodeStatus[tid] == Unblocking) { any_unblocking = true; @@ -447,10 +447,6 @@ void DefaultDecode::sortInsts() { int insts_from_fetch = fromFetch->size; -#ifdef DEBUG - for (int i=0; i < numThreads; i++) - assert(insts[i].empty()); -#endif for (int i = 0; i < insts_from_fetch; ++i) { insts[fromFetch->insts[i]->threadNumber].push(fromFetch->insts[i]); } @@ -458,7 +454,7 @@ DefaultDecode::sortInsts() template void -DefaultDecode::readStallSignals(unsigned tid) +DefaultDecode::readStallSignals(ThreadID tid) { if (fromRename->renameBlock[tid]) { stalls[tid].rename = true; @@ -490,7 +486,7 @@ DefaultDecode::readStallSignals(unsigned tid) template bool -DefaultDecode::checkSignalsAndUpdate(unsigned tid) +DefaultDecode::checkSignalsAndUpdate(ThreadID tid) { // Check if there's a squash signal, squash if there is. // Check stall signals, block if necessary. @@ -565,13 +561,14 @@ DefaultDecode::tick() toRenameIndex = 0; - list::iterator threads = (*activeThreads).begin(); + list::iterator threads = activeThreads->begin(); + list::iterator end = activeThreads->end(); sortInsts(); //Check stall and squash signals. - while (threads != (*activeThreads).end()) { - unsigned tid = *threads++; + while (threads != end) { + ThreadID tid = *threads++; DPRINTF(Decode,"Processing [tid:%i]\n",tid); status_change = checkSignalsAndUpdate(tid) || status_change; @@ -592,7 +589,7 @@ DefaultDecode::tick() template void -DefaultDecode::decode(bool &status_change, unsigned tid) +DefaultDecode::decode(bool &status_change, ThreadID tid) { // If status is Running or idle, // call decodeInsts() @@ -611,7 +608,7 @@ DefaultDecode::decode(bool &status_change, unsigned tid) // will allow, as long as it is not currently blocked. if (decodeStatus[tid] == Running || decodeStatus[tid] == Idle) { - DPRINTF(Decode, "[tid:%u] Not blocked, so attempting to run " + DPRINTF(Decode, "[tid:%u]: Not blocked, so attempting to run " "stage.\n",tid); decodeInsts(tid); @@ -637,7 +634,7 @@ DefaultDecode::decode(bool &status_change, unsigned tid) template void -DefaultDecode::decodeInsts(unsigned tid) +DefaultDecode::decodeInsts(ThreadID tid) { // Instructions can come either from the skid buffer or the list of // instructions coming from fetch, depending on decode's status. @@ -674,13 +671,12 @@ DefaultDecode::decodeInsts(unsigned tid) insts_to_decode.pop(); DPRINTF(Decode, "[tid:%u]: Processing instruction [sn:%lli] with " - "PC %#x\n", - tid, inst->seqNum, inst->readPC()); + "PC %s\n", tid, inst->seqNum, inst->pcState()); if (inst->isSquashed()) { - DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %#x is " + DPRINTF(Decode, "[tid:%u]: Instruction %i with PC %s is " "squashed, skipping.\n", - tid, inst->seqNum, inst->readPC()); + tid, inst->seqNum, inst->pcState()); ++decodeSquashedInsts; @@ -707,9 +703,13 @@ DefaultDecode::decodeInsts(unsigned tid) ++decodeDecodedInsts; --insts_available; +#if TRACING_ON + inst->decodeTick = curTick(); +#endif + // Ensure that if it was predicted as a branch, it really is a // branch. - if (inst->predTaken() && !inst->isControl()) { + if (inst->readPredTaken() && !inst->isControl()) { panic("Instruction predicted as a branch!"); ++decodeControlMispred; @@ -725,14 +725,18 @@ DefaultDecode::decodeInsts(unsigned tid) if (inst->isDirectCtrl() && inst->isUncondCtrl()) { ++decodeBranchResolved; - if (inst->branchTarget() != inst->readPredTarg()) { + if (!(inst->branchTarget() == inst->readPredTarg())) { ++decodeBranchMispred; // Might want to set some sort of boolean and just do // a check at the end squash(inst, inst->threadNumber); - inst->setPredTarg(inst->branchTarget()); + TheISA::PCState target = inst->branchTarget(); + DPRINTF(Decode, "[sn:%i]: Updating predictions: PredPC: %s\n", + inst->seqNum, target); + //The micro pc after an instruction level branch should be 0 + inst->setPredTarg(target); break; } }