diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/base.hh --- a/src/cpu/base.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/base.hh Tue Oct 23 20:41:17 2012 +0200 @@ -85,6 +85,25 @@ virtual const char *description() const; }; +namespace Enums { + /** Reasons why stages remained blocked . */ + enum Blockers { + BlockContextSwitch, + BlockDecode, + BlockRename, + BlockIEW, + BlockCommit, + BlockROB, + BlockIQ, + BlockLSQ, + BlockOther, + NumBlockers + }; + + + extern const char* BlockersStrings[NumBlockers]; +} + class BaseCPU : public MemObject { protected: diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/base.cc --- a/src/cpu/base.cc Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/base.cc Tue Oct 23 20:41:17 2012 +0200 @@ -78,6 +78,20 @@ // been initialized int maxThreadsPerCPU = 1; +namespace Enums { + const char* BlockersStrings[] = { + [BlockContextSwitch] = "BlockContextSwitch", + [BlockDecode] = "BlockDecode", + [BlockRename] = "BlockRename", + [BlockIEW] = "BlockIEW", + [BlockCommit] = "BlockCommit", + [BlockROB] = "BlockROB", + [BlockIQ] = "BlockIQ", + [BlockLSQ] = "BlockLSQ", + [BlockOther] = "BlockOther", + }; +} + CPUProgressEvent::CPUProgressEvent(BaseCPU *_cpu, Tick ival) : Event(Event::Progress_Event_Pri), _interval(ival), lastNumInst(0), cpu(_cpu), _repeatEvent(true) diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/decode.hh --- a/src/cpu/o3/decode.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/decode.hh Tue Oct 23 20:41:17 2012 +0200 @@ -162,7 +162,7 @@ bool checkSignalsAndUpdate(ThreadID tid); /** Checks all stall signals, and returns if any are true. */ - bool checkStall(ThreadID tid) const; + bool checkStall(ThreadID tid, bool updateStats = false); /** Returns if there any instructions from fetch on this cycle. */ inline bool fetchInstsValid(); @@ -291,6 +291,8 @@ Stats::Scalar decodeIdleCycles; /** Stat for total number of blocked cycles. */ Stats::Scalar decodeBlockedCycles; + /** Stat for total number of blocked cycles for each blocking "reason". */ + Stats::Vector2d decodeBlockedCyclesType; /** Stat for total number of normal running cycles. */ Stats::Scalar decodeRunCycles; /** Stat for total number of unblocking cycles. */ diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/decode_impl.hh --- a/src/cpu/o3/decode_impl.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/decode_impl.hh Tue Oct 23 20:41:17 2012 +0200 @@ -37,6 +37,7 @@ #include "debug/Decode.hh" #include "params/DerivO3CPU.hh" #include "sim/full_system.hh" +#include "cpu/base.hh" // clang complains about std::set being overloaded with Packet::set if // we open up the entire namespace std @@ -86,6 +87,12 @@ .name(name() + ".BlockedCycles") .desc("Number of cycles decode is blocked") .prereq(decodeBlockedCycles); + decodeBlockedCyclesType + .init(numThreads, Enums::NumBlockers) + .name(name() + ".BlockedCyclesType") + .desc("Number of cycles decode has spent blocked") + .prereq(decodeBlockedCycles) + .ysubnames(Enums::BlockersStrings); decodeRunCycles .name(name() + ".RunCycles") .desc("Number of cycles decode is running") @@ -196,19 +203,27 @@ template bool -DefaultDecode::checkStall(ThreadID tid) const +DefaultDecode::checkStall(ThreadID tid, bool updateStats) { bool ret_val = false; + Enums::Blockers blocker = Enums::BlockOther; if (stalls[tid].rename) { DPRINTF(Decode,"[tid:%i]: Stall fom Rename stage detected.\n", tid); ret_val = true; + blocker = Enums::BlockRename; } else if (stalls[tid].iew) { DPRINTF(Decode,"[tid:%i]: Stall fom IEW stage detected.\n", tid); ret_val = true; + blocker = Enums::BlockIEW; } else if (stalls[tid].commit) { DPRINTF(Decode,"[tid:%i]: Stall fom Commit stage detected.\n", tid); ret_val = true; + blocker = Enums::BlockCommit; + } + + if (updateStats && ret_val) { + decodeBlockedCyclesType[tid][blocker]++; } return ret_val; @@ -604,6 +619,7 @@ // check if stall conditions have passed if (decodeStatus[tid] == Blocked) { + checkStall(tid, true); ++decodeBlockedCycles; } else if (decodeStatus[tid] == Squashing) { ++decodeSquashCycles; diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/fetch.hh --- a/src/cpu/o3/fetch.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/fetch.hh Tue Oct 23 20:41:17 2012 +0200 @@ -301,7 +301,7 @@ const InstSeqNum seq_num, ThreadID tid); /** Checks if a thread is stalled. */ - bool checkStall(ThreadID tid) const; + bool checkStall(ThreadID tid, bool updateStats = false); /** Updates overall fetch stage status; to be called at the end of each * cycle. */ @@ -523,6 +523,8 @@ Stats::Scalar fetchIdleCycles; /** Total number of cycles spent blocked. */ Stats::Scalar fetchBlockedCycles; + /** Total number of cycles spent blocked for each blocking "reason". */ + Stats::Vector2d fetchBlockedCyclesType; /** Total number of cycles spent in any other state. */ Stats::Scalar fetchMiscStallCycles; /** Total number of cycles spent in waiting for drains. */ diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/fetch_impl.hh --- a/src/cpu/o3/fetch_impl.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/fetch_impl.hh Tue Oct 23 20:41:17 2012 +0200 @@ -194,6 +194,12 @@ .name(name() + ".BlockedCycles") .desc("Number of cycles fetch has spent blocked") .prereq(fetchBlockedCycles); + fetchBlockedCyclesType + .init(numThreads, Enums::NumBlockers) + .name(name() + ".BlockedCyclesType") + .desc("Number of cycles fetch has spent blocked") + .prereq(fetchBlockedCycles) + .ysubnames(Enums::BlockersStrings); fetchedCacheLines .name(name() + ".CacheLines") @@ -750,25 +756,35 @@ template bool -DefaultFetch::checkStall(ThreadID tid) const +DefaultFetch::checkStall(ThreadID tid, bool updateStats) { bool ret_val = false; + Enums::Blockers blocker = Enums::BlockOther; if (cpu->contextSwitch) { DPRINTF(Fetch,"[tid:%i]: Stalling for a context switch.\n",tid); ret_val = true; - } else if (stalls[tid].decode) { + blocker = Enums::BlockContextSwitch; + } else if (stalls[tid].decode) { DPRINTF(Fetch,"[tid:%i]: Stall from Decode stage detected.\n",tid); ret_val = true; + blocker = Enums::BlockDecode; } else if (stalls[tid].rename) { DPRINTF(Fetch,"[tid:%i]: Stall from Rename stage detected.\n",tid); ret_val = true; + blocker = Enums::BlockRename; } else if (stalls[tid].iew) { DPRINTF(Fetch,"[tid:%i]: Stall from IEW stage detected.\n",tid); ret_val = true; + blocker = Enums::BlockIEW; } else if (stalls[tid].commit) { DPRINTF(Fetch,"[tid:%i]: Stall from Commit stage detected.\n",tid); ret_val = true; + blocker = Enums::BlockCommit; + } + + if (updateStats && ret_val) { + fetchBlockedCyclesType[tid][blocker]++; } return ret_val; @@ -1575,6 +1591,7 @@ DPRINTF(Fetch, "Fetch has no active thread!\n"); } else if (fetchStatus[tid] == Blocked) { ++fetchBlockedCycles; + checkStall(tid, true); DPRINTF(Fetch, "[tid:%i]: Fetch is blocked!\n", tid); } else if (fetchStatus[tid] == Squashing) { ++fetchSquashCycles; diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/iew.hh --- a/src/cpu/o3/iew.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/iew.hh Tue Oct 23 20:41:17 2012 +0200 @@ -313,7 +313,7 @@ void readStallSignals(ThreadID tid); /** Checks if any of the stall conditions are currently true. */ - bool checkStall(ThreadID tid); + bool checkStall(ThreadID tid, bool updateState = false); /** Processes inputs and changes state accordingly. */ void checkSignalsAndUpdate(ThreadID tid); @@ -479,6 +479,8 @@ Stats::Scalar iewSquashCycles; /** Stat for total number of blocking cycles. */ Stats::Scalar iewBlockCycles; + /** Stat for total number of blocking cycles for each blocking "reason". */ + Stats::Vector2d iewBlockCyclesType; /** Stat for total number of unblocking cycles. */ Stats::Scalar iewUnblockCycles; /** Stat for total number of instructions dispatched. */ diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/iew_impl.hh --- a/src/cpu/o3/iew_impl.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/iew_impl.hh Tue Oct 23 20:41:17 2012 +0200 @@ -128,6 +128,12 @@ iewBlockCycles .name(name() + ".iewBlockCycles") .desc("Number of cycles IEW is blocking"); + iewBlockCyclesType + .init(numThreads, Enums::NumBlockers) + .name(name() + ".iewBlockCyclesType") + .desc("Number of cycles IEW is blocking") + .prereq(iewBlockCycles) + .ysubnames(Enums::BlockersStrings); iewUnblockCycles .name(name() + ".iewUnblockCycles") @@ -755,16 +761,19 @@ template bool -DefaultIEW::checkStall(ThreadID tid) +DefaultIEW::checkStall(ThreadID tid, bool updateStats) { bool ret_val(false); + Enums::Blockers blocker = Enums::BlockOther; if (stalls[tid].commit) { DPRINTF(IEW,"[tid:%i]: Stall from Commit stage detected.\n",tid); ret_val = true; + blocker = Enums::BlockCommit; } else if (instQueue.isFull(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: IQ is full.\n",tid); ret_val = true; + blocker = Enums::BlockIQ; } else if (ldstQueue.isFull(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: LSQ is full\n",tid); @@ -781,9 +790,15 @@ } ret_val = true; + blocker = Enums::BlockLSQ; } else if (ldstQueue.isStalled(tid)) { DPRINTF(IEW,"[tid:%i]: Stall: LSQ stall detected.\n",tid); ret_val = true; + blocker = Enums::BlockLSQ; + } + + if (updateStats && ret_val) { + iewBlockCyclesType[tid][blocker]++; } return ret_val; @@ -825,7 +840,7 @@ return; } - if (checkStall(tid)) { + if (checkStall(tid, dispatchStatus[tid] == Blocked)) { block(tid); dispatchStatus[tid] = Blocked; return; diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/rename.hh --- a/src/cpu/o3/rename.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/rename.hh Tue Oct 23 20:41:17 2012 +0200 @@ -249,7 +249,7 @@ void readStallSignals(ThreadID tid); /** Checks if any stages are telling rename to block. */ - bool checkStall(ThreadID tid); + bool checkStall(ThreadID tid, bool updateStats = false); /** Gets the number of free entries for a specific thread. */ void readFreeEntries(ThreadID tid); @@ -447,6 +447,8 @@ Stats::Scalar renameIdleCycles; /** Stat for total number of cycles spent blocking. */ Stats::Scalar renameBlockCycles; + /** Stat for total number of cycles spent blocking for each blocking "reason". */ + Stats::Vector2d renameBlockCyclesType; /** Stat for total number of cycles spent stalling for a serializing inst. */ Stats::Scalar renameSerializeStallCycles; /** Stat for total number of cycles spent running normally. */ diff -r f634a34f2f0b -r a22e4e38f1a4 src/cpu/o3/rename_impl.hh --- a/src/cpu/o3/rename_impl.hh Tue Oct 23 04:49:48 2012 -0400 +++ b/src/cpu/o3/rename_impl.hh Tue Oct 23 20:41:17 2012 +0200 @@ -113,6 +113,12 @@ .name(name() + ".BlockCycles") .desc("Number of cycles rename is blocking") .prereq(renameBlockCycles); + renameBlockCyclesType + .init(numThreads, Enums::NumBlockers) + .name(name() + ".BlockCyclesType") + .desc("Number of cycles rename has spent blocked") + .prereq(renameBlockCycles) + .ysubnames(Enums::BlockersStrings); renameSerializeStallCycles .name(name() + ".serializeStallCycles") .desc("count of cycles rename stalled for serializing inst") @@ -462,6 +468,7 @@ // check if stall conditions have passed if (renameStatus[tid] == Blocked) { + checkStall(tid, true); ++renameBlockCycles; } else if (renameStatus[tid] == Squashing) { ++renameSquashCycles; @@ -1171,34 +1178,46 @@ template bool -DefaultRename::checkStall(ThreadID tid) +DefaultRename::checkStall(ThreadID tid, bool updateStats) { bool ret_val = false; + Enums::Blockers blocker = Enums::BlockOther; if (stalls[tid].iew) { DPRINTF(Rename,"[tid:%i]: Stall from IEW stage detected.\n", tid); ret_val = true; + blocker = Enums::BlockIEW; } else if (stalls[tid].commit) { DPRINTF(Rename,"[tid:%i]: Stall from Commit stage detected.\n", tid); ret_val = true; + blocker = Enums::BlockCommit; } else if (calcFreeROBEntries(tid) <= 0) { DPRINTF(Rename,"[tid:%i]: Stall: ROB has 0 free entries.\n", tid); ret_val = true; + blocker = Enums::BlockROB; } else if (calcFreeIQEntries(tid) <= 0) { DPRINTF(Rename,"[tid:%i]: Stall: IQ has 0 free entries.\n", tid); ret_val = true; + blocker = Enums::BlockIQ; } else if (calcFreeLSQEntries(tid) <= 0) { DPRINTF(Rename,"[tid:%i]: Stall: LSQ has 0 free entries.\n", tid); ret_val = true; + blocker = Enums::BlockLSQ; } else if (renameMap[tid]->numFreeEntries() <= 0) { DPRINTF(Rename,"[tid:%i]: Stall: RenameMap has 0 free entries.\n", tid); ret_val = true; + blocker = Enums::BlockRename; } else if (renameStatus[tid] == SerializeStall && (!emptyROB[tid] || instsInProgress[tid])) { DPRINTF(Rename,"[tid:%i]: Stall: Serialize stall and ROB is not " "empty.\n", tid); ret_val = true; + blocker = Enums::BlockOther; + } + + if (updateStats && ret_val) { + renameBlockCyclesType[tid][blocker]++; } return ret_val;