using namespace Stats;
instQueue.regStats();
- ldstQueue.regStats();
iewIdleCycles
.name(name() + ".iewIdleCycles")
/** Returns the name of the LSQ. */
std::string name() const;
- /** Registers statistics of each LSQ unit. */
- void regStats();
-
/** Sets the pointer to the list of active threads. */
void setActiveThreads(std::list<ThreadID> *at_ptr);
return iewStage->name() + ".lsq";
}
-template<class Impl>
-void
-LSQ<Impl>::regStats()
-{
- //Initialize LSQs
- for (ThreadID tid = 0; tid < numThreads; tid++) {
- thread[tid].regStats();
- }
-}
-
template<class Impl>
void
LSQ<Impl>::setActiveThreads(list<ThreadID> *at_ptr)
#include <algorithm>
#include <cstring>
#include <map>
+#include <memory>
#include <queue>
#include "arch/generic/debugfaults.hh"
* contructor is deleted explicitly. However, STL vector requires
* a valid copy constructor for the base type at compile time.
*/
- LSQUnit(const LSQUnit &l) { panic("LSQUnit is not copy-able"); }
+ LSQUnit(const LSQUnit &l): stats(nullptr)
+ {
+ panic("LSQUnit is not copy-able");
+ }
/** Initializes the LSQ unit with the specified number of entries. */
void init(O3CPU *cpu_ptr, IEW *iew_ptr, DerivO3CPUParams *params,
/** Returns the name of the LSQ unit. */
std::string name() const;
- /** Registers statistics. */
- void regStats();
-
/** Sets the pointer to the dcache port. */
void setDcachePort(RequestPort *dcache_port);
/** Flag for memory model. */
bool needsTSO;
+ protected:
// Will also need how many read/write ports the Dcache has. Or keep track
// of that in stage that is one level up, and only call executeLoad/Store
// the appropriate number of times.
- /** Total number of loads forwaded from LSQ stores. */
- Stats::Scalar lsqForwLoads;
-
- /** Total number of loads ignored due to invalid addresses. */
- Stats::Scalar invAddrLoads;
-
- /** Total number of squashed loads. */
- Stats::Scalar lsqSquashedLoads;
+ struct LSQUnitStats : public Stats::Group{
+ LSQUnitStats(Stats::Group *parent);
- /** Total number of responses from the memory system that are
- * ignored due to the instruction already being squashed. */
- Stats::Scalar lsqIgnoredResponses;
+ /** Total number of loads forwaded from LSQ stores. */
+ Stats::Scalar forwLoads;
- /** Tota number of memory ordering violations. */
- Stats::Scalar lsqMemOrderViolation;
+ /** Total number of squashed loads. */
+ Stats::Scalar squashedLoads;
- /** Total number of squashed stores. */
- Stats::Scalar lsqSquashedStores;
+ /** Total number of responses from the memory system that are
+ * ignored due to the instruction already being squashed. */
+ Stats::Scalar ignoredResponses;
- /** Total number of software prefetches ignored due to invalid addresses. */
- Stats::Scalar invAddrSwpfs;
+ /** Tota number of memory ordering violations. */
+ Stats::Scalar memOrderViolation;
- /** Ready loads blocked due to partial store-forwarding. */
- Stats::Scalar lsqBlockedLoads;
+ /** Total number of squashed stores. */
+ Stats::Scalar squashedStores;
- /** Number of loads that were rescheduled. */
- Stats::Scalar lsqRescheduledLoads;
+ /** Number of loads that were rescheduled. */
+ Stats::Scalar rescheduledLoads;
- /** Number of times the LSQ is blocked due to the cache. */
- Stats::Scalar lsqCacheBlocked;
+ /** Number of times the LSQ is blocked due to the cache. */
+ Stats::Scalar blockedByCache;
+ } stats;
public:
/** Executes the load at the given index. */
iewStage->rescheduleMemInst(load_inst);
load_inst->clearIssued();
load_inst->effAddrValid(false);
- ++lsqRescheduledLoads;
+ ++stats.rescheduledLoads;
DPRINTF(LSQUnit, "Strictly ordered load [sn:%lli] PC %s\n",
load_inst->seqNum, load_inst->pcState());
cpu->schedule(wb, curTick());
// Don't need to do anything special for split loads.
- ++lsqForwLoads;
+ ++stats.forwLoads;
return NoFault;
} else if (coverage == AddrRangeCoverage::PartialAddrRangeCoverage) {
iewStage->rescheduleMemInst(load_inst);
load_inst->clearIssued();
load_inst->effAddrValid(false);
- ++lsqRescheduledLoads;
+ ++stats.rescheduledLoads;
// Do not generate a writeback event as this instruction is not
// complete.
lastRetiredHtmUid(0),
cacheBlockMask(0), stalled(false),
isStoreBlocked(false), storeInFlight(false), hasPendingRequest(false),
- pendingRequest(nullptr)
+ pendingRequest(nullptr), stats(nullptr)
{
}
lsq = lsq_ptr;
+ cpu->addStatGroup(csprintf("lsq%i", lsqID).c_str(), &stats);
+
DPRINTF(LSQUnit, "Creating LSQUnit%i object.\n",lsqID);
depCheckShift = params->LSQDepCheckShift;
}
}
-template<class Impl>
-void
-LSQUnit<Impl>::regStats()
+template <class Impl>
+LSQUnit<Impl>::LSQUnitStats::LSQUnitStats(Stats::Group *parent)
+ : Stats::Group(parent),
+ ADD_STAT(forwLoads, "Number of loads that had data forwarded from"
+ " stores"),
+ ADD_STAT(squashedLoads, "Number of loads squashed"),
+ ADD_STAT(ignoredResponses, "Number of memory responses ignored"
+ " because the instruction is squashed"),
+ ADD_STAT(memOrderViolation, "Number of memory ordering violations"),
+ ADD_STAT(squashedStores, "Number of stores squashed"),
+ ADD_STAT(rescheduledLoads, "Number of loads that were rescheduled"),
+ ADD_STAT(blockedByCache, "Number of times an access to memory failed"
+ " due to the cache being blocked")
{
- lsqForwLoads
- .name(name() + ".forwLoads")
- .desc("Number of loads that had data forwarded from stores");
-
- invAddrLoads
- .name(name() + ".invAddrLoads")
- .desc("Number of loads ignored due to an invalid address");
-
- lsqSquashedLoads
- .name(name() + ".squashedLoads")
- .desc("Number of loads squashed");
-
- lsqIgnoredResponses
- .name(name() + ".ignoredResponses")
- .desc("Number of memory responses ignored because the instruction is squashed");
-
- lsqMemOrderViolation
- .name(name() + ".memOrderViolation")
- .desc("Number of memory ordering violations");
-
- lsqSquashedStores
- .name(name() + ".squashedStores")
- .desc("Number of stores squashed");
-
- invAddrSwpfs
- .name(name() + ".invAddrSwpfs")
- .desc("Number of software prefetches ignored due to an invalid address");
-
- lsqBlockedLoads
- .name(name() + ".blockedLoads")
- .desc("Number of blocked loads due to partial load-store forwarding");
-
- lsqRescheduledLoads
- .name(name() + ".rescheduledLoads")
- .desc("Number of loads that were rescheduled");
-
- lsqCacheBlocked
- .name(name() + ".cacheBlocked")
- .desc("Number of times an access to memory failed due to the cache being blocked");
}
template<class Impl>
inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
memDepViolator = ld_inst;
- ++lsqMemOrderViolation;
+ ++stats.memOrderViolation;
return std::make_shared<GenericISA::M5PanicFault>(
"Detected fault with inst [sn:%lli] and "
inst->seqNum, ld_inst->seqNum, ld_eff_addr1);
memDepViolator = ld_inst;
- ++lsqMemOrderViolation;
+ ++stats.memOrderViolation;
return std::make_shared<GenericISA::M5PanicFault>(
"Detected fault with "
--loads;
loadQueue.pop_back();
- ++lsqSquashedLoads;
+ ++stats.squashedLoads;
}
// hardware transactional memory
--stores;
storeQueue.pop_back();
- ++lsqSquashedStores;
+ ++stats.squashedStores;
}
}
// Squashed instructions do not need to complete their access.
if (inst->isSquashed()) {
assert (!inst->isStore() || inst->isStoreConditional());
- ++lsqIgnoredResponses;
+ ++stats.ignoredResponses;
return;
}
} else {
if (cache_got_blocked) {
lsq->cacheBlocked(true);
- ++lsqCacheBlocked;
+ ++stats.blockedByCache;
}
if (!isLoad) {
assert(state->request() == storeWBIt->request());