summaryrefslogtreecommitdiff
path: root/src/mem/dram_ctrl.cc
diff options
context:
space:
mode:
authorAndreas Sandberg <andreas.sandberg@arm.com>2019-09-23 18:20:23 +0100
committerAndreas Sandberg <andreas.sandberg@arm.com>2019-09-30 12:33:47 +0000
commit76384ec3ff2a52898aa35a27d337194ae557648a (patch)
treef403d38cb5fb050b60f5299d60d908abc504ecf4 /src/mem/dram_ctrl.cc
parenta060ac86307311587d05d280ee1f4cbdb84fe98a (diff)
downloadgem5-76384ec3ff2a52898aa35a27d337194ae557648a.tar.xz
mem: Convert DRAM controller to new-style stats
Note that this changes the stat format used by the DRAM controller. Previously, it would have a structure looking a bit like this: - system - dram: Main DRAM controller - dram_0: Rank 0 - dram_1: Rank 1 This structure can't be replicated with new-world stats since stats are confined to the SimObject name space. This means that the new structure looks like this: - system - dram: Main DRAM controller - rank0: Rank 0 - rank1: Rank 1 Change-Id: I7435cfaf137c94b0c18de619d816362dd0da8125 Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/21142 Maintainer: Nikos Nikoleris <nikos.nikoleris@arm.com> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Carvalho <odanrc@yahoo.com.br> Reviewed-by: Wendy Elsasser <wendy.elsasser@arm.com>
Diffstat (limited to 'src/mem/dram_ctrl.cc')
-rw-r--r--src/mem/dram_ctrl.cc711
1 files changed, 301 insertions, 410 deletions
diff --git a/src/mem/dram_ctrl.cc b/src/mem/dram_ctrl.cc
index 06c540ba6..1352dbfbe 100644
--- a/src/mem/dram_ctrl.cc
+++ b/src/mem/dram_ctrl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2018 ARM Limited
+ * Copyright (c) 2010-2019 ARM Limited
* All rights reserved
*
* The license below extends only to copyright in the software and shall
@@ -96,7 +96,9 @@ DRAMCtrl::DRAMCtrl(const DRAMCtrlParams* p) :
frontendLatency(p->static_frontend_latency),
backendLatency(p->static_backend_latency),
nextBurstAt(0), prevArrival(0),
- nextReqTime(0), activeRank(0), timeStampOffset(0),
+ nextReqTime(0),
+ stats(*this),
+ activeRank(0), timeStampOffset(0),
lastStatsResetTick(0), enableDRAMPowerdown(p->enable_dram_powerdown)
{
// sanity check the ranks since we rely on bit slicing for the
@@ -429,9 +431,9 @@ DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
for (int cnt = 0; cnt < pktCount; ++cnt) {
unsigned size = std::min((addr | (burstSize - 1)) + 1,
pkt->getAddr() + pkt->getSize()) - addr;
- readPktSize[ceilLog2(size)]++;
- readBursts++;
- masterReadAccesses[pkt->masterId()]++;
+ stats.readPktSize[ceilLog2(size)]++;
+ stats.readBursts++;
+ stats.masterReadAccesses[pkt->masterId()]++;
// First check write buffer to see if the data is already at
// the controller
@@ -448,13 +450,13 @@ DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
((addr + size) <= (p->addr + p->size))) {
foundInWrQ = true;
- servicedByWrQ++;
+ stats.servicedByWrQ++;
pktsServicedByWrQ++;
DPRINTF(DRAM,
"Read to addr %lld with size %d serviced by "
"write queue\n",
addr, size);
- bytesReadWrQ += burstSize;
+ stats.bytesReadWrQ += burstSize;
break;
}
}
@@ -476,7 +478,7 @@ DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
dram_pkt->burstHelper = burst_helper;
assert(!readQueueFull(1));
- rdQLenPdf[totalReadQueueSize + respQueue.size()]++;
+ stats.rdQLenPdf[totalReadQueueSize + respQueue.size()]++;
DPRINTF(DRAM, "Adding to read queue\n");
@@ -489,7 +491,7 @@ DRAMCtrl::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
dram_pkt->addr, 1);
// Update stats
- avgRdQLen = totalReadQueueSize + respQueue.size();
+ stats.avgRdQLen = totalReadQueueSize + respQueue.size();
}
// Starting address of next dram pkt (aligend to burstSize boundary)
@@ -527,9 +529,9 @@ DRAMCtrl::addToWriteQueue(PacketPtr pkt, unsigned int pktCount)
for (int cnt = 0; cnt < pktCount; ++cnt) {
unsigned size = std::min((addr | (burstSize - 1)) + 1,
pkt->getAddr() + pkt->getSize()) - addr;
- writePktSize[ceilLog2(size)]++;
- writeBursts++;
- masterWriteAccesses[pkt->masterId()]++;
+ stats.writePktSize[ceilLog2(size)]++;
+ stats.writeBursts++;
+ stats.masterWriteAccesses[pkt->masterId()]++;
// see if we can merge with an existing item in the write
// queue and keep track of whether we have merged or not
@@ -542,7 +544,7 @@ DRAMCtrl::addToWriteQueue(PacketPtr pkt, unsigned int pktCount)
DRAMPacket* dram_pkt = decodeAddr(pkt, addr, size, false);
assert(totalWriteQueueSize < writeBufferSize);
- wrQLenPdf[totalWriteQueueSize]++;
+ stats.wrQLenPdf[totalWriteQueueSize]++;
DPRINTF(DRAM, "Adding to write queue\n");
@@ -556,7 +558,7 @@ DRAMCtrl::addToWriteQueue(PacketPtr pkt, unsigned int pktCount)
assert(totalWriteQueueSize == isInWriteQueue.size());
// Update stats
- avgWrQLen = totalWriteQueueSize;
+ stats.avgWrQLen = totalWriteQueueSize;
// increment write entries of the rank
++dram_pkt->rankRef.writeEntries;
@@ -565,7 +567,7 @@ DRAMCtrl::addToWriteQueue(PacketPtr pkt, unsigned int pktCount)
// keep track of the fact that this burst effectively
// disappeared as it was merged with an existing one
- mergedWrBursts++;
+ stats.mergedWrBursts++;
}
// Starting address of next dram pkt (aligend to burstSize boundary)
@@ -627,7 +629,7 @@ DRAMCtrl::recvTimingReq(PacketPtr pkt)
// Calc avg gap between requests
if (prevArrival != 0) {
- totGap += curTick() - prevArrival;
+ stats.totGap += curTick() - prevArrival;
}
prevArrival = curTick();
@@ -650,12 +652,12 @@ DRAMCtrl::recvTimingReq(PacketPtr pkt)
DPRINTF(DRAM, "Write queue full, not accepting\n");
// remember that we have to retry this port
retryWrReq = true;
- numWrRetry++;
+ stats.numWrRetry++;
return false;
} else {
addToWriteQueue(pkt, dram_pkt_count);
- writeReqs++;
- bytesWrittenSys += size;
+ stats.writeReqs++;
+ stats.bytesWrittenSys += size;
}
} else {
assert(pkt->isRead());
@@ -664,12 +666,12 @@ DRAMCtrl::recvTimingReq(PacketPtr pkt)
DPRINTF(DRAM, "Read queue full, not accepting\n");
// remember that we have to retry this port
retryRdReq = true;
- numRdRetry++;
+ stats.numRdRetry++;
return false;
} else {
addToReadQueue(pkt, dram_pkt_count);
- readReqs++;
- bytesReadSys += size;
+ stats.readReqs++;
+ stats.bytesReadSys += size;
}
}
@@ -1059,7 +1061,7 @@ DRAMCtrl::prechargeBank(Rank& rank_ref, Bank& bank, Tick pre_at, bool trace)
// sample the bytes per activate here since we are closing
// the page
- bytesPerActivate.sample(bank.bytesAccessed);
+ stats.bytesPerActivate.sample(bank.bytesAccessed);
bank.openRow = Bank::NO_ROW;
@@ -1304,26 +1306,26 @@ DRAMCtrl::doDRAMAccess(DRAMPacket* dram_pkt)
if (dram_pkt->isRead()) {
++readsThisTime;
if (row_hit)
- readRowHits++;
- bytesReadDRAM += burstSize;
- perBankRdBursts[dram_pkt->bankId]++;
+ stats.readRowHits++;
+ stats.bytesReadDRAM += burstSize;
+ stats.perBankRdBursts[dram_pkt->bankId]++;
// Update latency stats
- totMemAccLat += dram_pkt->readyTime - dram_pkt->entryTime;
- masterReadTotalLat[dram_pkt->masterId()] +=
+ stats.totMemAccLat += dram_pkt->readyTime - dram_pkt->entryTime;
+ stats.masterReadTotalLat[dram_pkt->masterId()] +=
dram_pkt->readyTime - dram_pkt->entryTime;
- totBusLat += tBURST;
- totQLat += cmd_at - dram_pkt->entryTime;
- masterReadBytes[dram_pkt->masterId()] += dram_pkt->size;
+ stats.totBusLat += tBURST;
+ stats.totQLat += cmd_at - dram_pkt->entryTime;
+ stats.masterReadBytes[dram_pkt->masterId()] += dram_pkt->size;
} else {
++writesThisTime;
if (row_hit)
- writeRowHits++;
- bytesWritten += burstSize;
- perBankWrBursts[dram_pkt->bankId]++;
- masterWriteBytes[dram_pkt->masterId()] += dram_pkt->size;
- masterWriteTotalLat[dram_pkt->masterId()] +=
+ stats.writeRowHits++;
+ stats.bytesWritten += burstSize;
+ stats.perBankWrBursts[dram_pkt->bankId]++;
+ stats.masterWriteBytes[dram_pkt->masterId()] += dram_pkt->size;
+ stats.masterWriteTotalLat[dram_pkt->masterId()] +=
dram_pkt->readyTime - dram_pkt->entryTime;
}
}
@@ -1351,13 +1353,13 @@ DRAMCtrl::processNextReqEvent()
DPRINTF(DRAM,
"Switching to writes after %d reads with %d reads "
"waiting\n", readsThisTime, totalReadQueueSize);
- rdPerTurnAround.sample(readsThisTime);
+ stats.rdPerTurnAround.sample(readsThisTime);
readsThisTime = 0;
} else {
DPRINTF(DRAM,
"Switching to reads after %d writes with %d writes "
"waiting\n", writesThisTime, totalWriteQueueSize);
- wrPerTurnAround.sample(writesThisTime);
+ stats.wrPerTurnAround.sample(writesThisTime);
writesThisTime = 0;
}
}
@@ -1732,7 +1734,8 @@ DRAMCtrl::Rank::Rank(DRAMCtrl& _memory, const DRAMCtrlParams* _p, int rank)
prechargeEvent([this]{ processPrechargeEvent(); }, name()),
refreshEvent([this]{ processRefreshEvent(); }, name()),
powerEvent([this]{ processPowerEvent(); }, name()),
- wakeUpEvent([this]{ processWakeUpEvent(); }, name())
+ wakeUpEvent([this]{ processWakeUpEvent(); }, name()),
+ stats(_memory, *this)
{
for (int b = 0; b < _p->banks_per_rank; b++) {
banks[b].bank = b;
@@ -2237,12 +2240,12 @@ DRAMCtrl::Rank::processPowerEvent()
PowerState prev_state = pwrState;
// update the accounting
- pwrStateTime[prev_state] += duration;
+ stats.memoryStateTime[prev_state] += duration;
// track to total idle time
if ((prev_state == PWR_PRE_PDN) || (prev_state == PWR_ACT_PDN) ||
(prev_state == PWR_SREF)) {
- totalIdleTime += duration;
+ stats.totalIdleTime += duration;
}
pwrState = pwrStateTrans;
@@ -2380,28 +2383,28 @@ DRAMCtrl::Rank::updatePowerStats()
// The energy components inside the power lib are calculated over
// the window so accumulate into the corresponding gem5 stat
- actEnergy += energy.act_energy * memory.devicesPerRank;
- preEnergy += energy.pre_energy * memory.devicesPerRank;
- readEnergy += energy.read_energy * memory.devicesPerRank;
- writeEnergy += energy.write_energy * memory.devicesPerRank;
- refreshEnergy += energy.ref_energy * memory.devicesPerRank;
- actBackEnergy += energy.act_stdby_energy * memory.devicesPerRank;
- preBackEnergy += energy.pre_stdby_energy * memory.devicesPerRank;
- actPowerDownEnergy += energy.f_act_pd_energy * memory.devicesPerRank;
- prePowerDownEnergy += energy.f_pre_pd_energy * memory.devicesPerRank;
- selfRefreshEnergy += energy.sref_energy * memory.devicesPerRank;
+ stats.actEnergy += energy.act_energy * memory.devicesPerRank;
+ stats.preEnergy += energy.pre_energy * memory.devicesPerRank;
+ stats.readEnergy += energy.read_energy * memory.devicesPerRank;
+ stats.writeEnergy += energy.write_energy * memory.devicesPerRank;
+ stats.refreshEnergy += energy.ref_energy * memory.devicesPerRank;
+ stats.actBackEnergy += energy.act_stdby_energy * memory.devicesPerRank;
+ stats.preBackEnergy += energy.pre_stdby_energy * memory.devicesPerRank;
+ stats.actPowerDownEnergy += energy.f_act_pd_energy * memory.devicesPerRank;
+ stats.prePowerDownEnergy += energy.f_pre_pd_energy * memory.devicesPerRank;
+ stats.selfRefreshEnergy += energy.sref_energy * memory.devicesPerRank;
// Accumulate window energy into the total energy.
- totalEnergy += energy.window_energy * memory.devicesPerRank;
+ stats.totalEnergy += energy.window_energy * memory.devicesPerRank;
// Average power must not be accumulated but calculated over the time
// since last stats reset. SimClock::Frequency is tick period not tick
// frequency.
// energy (pJ) 1e-9
// power (mW) = ----------- * ----------
// time (tick) tick_frequency
- averagePower = (totalEnergy.value() /
- (curTick() - memory.lastStatsResetTick)) *
- (SimClock::Frequency / 1000000000.0);
+ stats.averagePower = (stats.totalEnergy.value() /
+ (curTick() - memory.lastStatsResetTick)) *
+ (SimClock::Frequency / 1000000000.0);
}
void
@@ -2413,9 +2416,8 @@ DRAMCtrl::Rank::computeStats()
updatePowerStats();
// final update of power state times
- pwrStateTime[pwrState] += (curTick() - pwrStateTick);
+ stats.memoryStateTime[pwrState] += (curTick() - pwrStateTick);
pwrStateTick = curTick();
-
}
void
@@ -2428,405 +2430,204 @@ DRAMCtrl::Rank::resetStats() {
}
-void
-DRAMCtrl::Rank::regStats()
+DRAMCtrl::DRAMStats::DRAMStats(DRAMCtrl &_dram)
+ : Stats::Group(&_dram),
+ dram(_dram),
+
+ ADD_STAT(readReqs, "Number of read requests accepted"),
+ ADD_STAT(writeReqs, "Number of write requests accepted"),
+
+ ADD_STAT(readBursts,
+ "Number of DRAM read bursts, "
+ "including those serviced by the write queue"),
+ ADD_STAT(writeBursts,
+ "Number of DRAM write bursts, "
+ "including those merged in the write queue"),
+ ADD_STAT(servicedByWrQ,
+ "Number of DRAM read bursts serviced by the write queue"),
+ ADD_STAT(mergedWrBursts,
+ "Number of DRAM write bursts merged with an existing one"),
+
+ ADD_STAT(neitherReadNorWriteReqs,
+ "Number of requests that are neither read nor write"),
+
+ ADD_STAT(perBankRdBursts, "Per bank write bursts"),
+ ADD_STAT(perBankWrBursts, "Per bank write bursts"),
+
+ ADD_STAT(avgRdQLen, "Average read queue length when enqueuing"),
+ ADD_STAT(avgWrQLen, "Average write queue length when enqueuing"),
+
+ ADD_STAT(totQLat, "Total ticks spent queuing"),
+ ADD_STAT(totBusLat, "Total ticks spent in databus transfers"),
+ ADD_STAT(totMemAccLat,
+ "Total ticks spent from burst creation until serviced "
+ "by the DRAM"),
+ ADD_STAT(avgQLat, "Average queueing delay per DRAM burst"),
+ ADD_STAT(avgBusLat, "Average bus latency per DRAM burst"),
+ ADD_STAT(avgMemAccLat, "Average memory access latency per DRAM burst"),
+
+ ADD_STAT(numRdRetry, "Number of times read queue was full causing retry"),
+ ADD_STAT(numWrRetry, "Number of times write queue was full causing retry"),
+
+ ADD_STAT(readRowHits, "Number of row buffer hits during reads"),
+ ADD_STAT(writeRowHits, "Number of row buffer hits during writes"),
+ ADD_STAT(readRowHitRate, "Row buffer hit rate for reads"),
+ ADD_STAT(writeRowHitRate, "Row buffer hit rate for writes"),
+
+ ADD_STAT(readPktSize, "Read request sizes (log2)"),
+ ADD_STAT(writePktSize, "Write request sizes (log2)"),
+
+ ADD_STAT(rdQLenPdf, "What read queue length does an incoming req see"),
+ ADD_STAT(wrQLenPdf, "What write queue length does an incoming req see"),
+
+ ADD_STAT(bytesPerActivate, "Bytes accessed per row activation"),
+
+ ADD_STAT(rdPerTurnAround,
+ "Reads before turning the bus around for writes"),
+ ADD_STAT(wrPerTurnAround,
+ "Writes before turning the bus around for reads"),
+
+ ADD_STAT(bytesReadDRAM, "Total number of bytes read from DRAM"),
+ ADD_STAT(bytesReadWrQ, "Total number of bytes read from write queue"),
+ ADD_STAT(bytesWritten, "Total number of bytes written to DRAM"),
+ ADD_STAT(bytesReadSys, "Total read bytes from the system interface side"),
+ ADD_STAT(bytesWrittenSys,
+ "Total written bytes from the system interface side"),
+
+ ADD_STAT(avgRdBW, "Average DRAM read bandwidth in MiByte/s"),
+ ADD_STAT(avgWrBW, "Average achieved write bandwidth in MiByte/s"),
+ ADD_STAT(avgRdBWSys, "Average system read bandwidth in MiByte/s"),
+ ADD_STAT(avgWrBWSys, "Average system write bandwidth in MiByte/s"),
+ ADD_STAT(peakBW, "Theoretical peak bandwidth in MiByte/s"),
+
+ ADD_STAT(busUtil, "Data bus utilization in percentage"),
+ ADD_STAT(busUtilRead, "Data bus utilization in percentage for reads"),
+ ADD_STAT(busUtilWrite, "Data bus utilization in percentage for writes"),
+
+ ADD_STAT(totGap, "Total gap between requests"),
+ ADD_STAT(avgGap, "Average gap between requests"),
+
+ ADD_STAT(masterReadBytes, "Per-master bytes read from memory"),
+ ADD_STAT(masterWriteBytes, "Per-master bytes write to memory"),
+ ADD_STAT(masterReadRate,
+ "Per-master bytes read from memory rate (Bytes/sec)"),
+ ADD_STAT(masterWriteRate,
+ "Per-master bytes write to memory rate (Bytes/sec)"),
+ ADD_STAT(masterReadAccesses,
+ "Per-master read serviced memory accesses"),
+ ADD_STAT(masterWriteAccesses,
+ "Per-master write serviced memory accesses"),
+ ADD_STAT(masterReadTotalLat,
+ "Per-master read total memory access latency"),
+ ADD_STAT(masterWriteTotalLat,
+ "Per-master write total memory access latency"),
+ ADD_STAT(masterReadAvgLat,
+ "Per-master read average memory access latency"),
+ ADD_STAT(masterWriteAvgLat,
+ "Per-master write average memory access latency"),
+
+ ADD_STAT(pageHitRate, "Row buffer hit rate, read and write combined")
{
- pwrStateTime
- .init(6)
- .name(name() + ".memoryStateTime")
- .desc("Time in different power states");
- pwrStateTime.subname(0, "IDLE");
- pwrStateTime.subname(1, "REF");
- pwrStateTime.subname(2, "SREF");
- pwrStateTime.subname(3, "PRE_PDN");
- pwrStateTime.subname(4, "ACT");
- pwrStateTime.subname(5, "ACT_PDN");
-
- actEnergy
- .name(name() + ".actEnergy")
- .desc("Energy for activate commands per rank (pJ)");
-
- preEnergy
- .name(name() + ".preEnergy")
- .desc("Energy for precharge commands per rank (pJ)");
-
- readEnergy
- .name(name() + ".readEnergy")
- .desc("Energy for read commands per rank (pJ)");
-
- writeEnergy
- .name(name() + ".writeEnergy")
- .desc("Energy for write commands per rank (pJ)");
-
- refreshEnergy
- .name(name() + ".refreshEnergy")
- .desc("Energy for refresh commands per rank (pJ)");
-
- actBackEnergy
- .name(name() + ".actBackEnergy")
- .desc("Energy for active background per rank (pJ)");
-
- preBackEnergy
- .name(name() + ".preBackEnergy")
- .desc("Energy for precharge background per rank (pJ)");
-
- actPowerDownEnergy
- .name(name() + ".actPowerDownEnergy")
- .desc("Energy for active power-down per rank (pJ)");
-
- prePowerDownEnergy
- .name(name() + ".prePowerDownEnergy")
- .desc("Energy for precharge power-down per rank (pJ)");
-
- selfRefreshEnergy
- .name(name() + ".selfRefreshEnergy")
- .desc("Energy for self refresh per rank (pJ)");
-
- totalEnergy
- .name(name() + ".totalEnergy")
- .desc("Total energy per rank (pJ)");
-
- averagePower
- .name(name() + ".averagePower")
- .desc("Core power per rank (mW)");
-
- totalIdleTime
- .name(name() + ".totalIdleTime")
- .desc("Total Idle time Per DRAM Rank");
-
- Stats::registerDumpCallback(new RankDumpCallback(this));
- Stats::registerResetCallback(new RankResetCallback(this));
}
+
void
-DRAMCtrl::regStats()
+DRAMCtrl::DRAMStats::regStats()
{
using namespace Stats;
- MemCtrl::regStats();
-
- for (auto r : ranks) {
- r->regStats();
- }
-
- registerResetCallback(new MemResetCallback(this));
-
- readReqs
- .name(name() + ".readReqs")
- .desc("Number of read requests accepted");
-
- writeReqs
- .name(name() + ".writeReqs")
- .desc("Number of write requests accepted");
-
- readBursts
- .name(name() + ".readBursts")
- .desc("Number of DRAM read bursts, "
- "including those serviced by the write queue");
-
- writeBursts
- .name(name() + ".writeBursts")
- .desc("Number of DRAM write bursts, "
- "including those merged in the write queue");
-
- servicedByWrQ
- .name(name() + ".servicedByWrQ")
- .desc("Number of DRAM read bursts serviced by the write queue");
-
- mergedWrBursts
- .name(name() + ".mergedWrBursts")
- .desc("Number of DRAM write bursts merged with an existing one");
-
- neitherReadNorWrite
- .name(name() + ".neitherReadNorWriteReqs")
- .desc("Number of requests that are neither read nor write");
-
- perBankRdBursts
- .init(banksPerRank * ranksPerChannel)
- .name(name() + ".perBankRdBursts")
- .desc("Per bank write bursts");
-
- perBankWrBursts
- .init(banksPerRank * ranksPerChannel)
- .name(name() + ".perBankWrBursts")
- .desc("Per bank write bursts");
-
- avgRdQLen
- .name(name() + ".avgRdQLen")
- .desc("Average read queue length when enqueuing")
- .precision(2);
-
- avgWrQLen
- .name(name() + ".avgWrQLen")
- .desc("Average write queue length when enqueuing")
- .precision(2);
-
- totQLat
- .name(name() + ".totQLat")
- .desc("Total ticks spent queuing");
-
- totBusLat
- .name(name() + ".totBusLat")
- .desc("Total ticks spent in databus transfers");
-
- totMemAccLat
- .name(name() + ".totMemAccLat")
- .desc("Total ticks spent from burst creation until serviced "
- "by the DRAM");
-
- avgQLat
- .name(name() + ".avgQLat")
- .desc("Average queueing delay per DRAM burst")
- .precision(2);
-
- avgQLat = totQLat / (readBursts - servicedByWrQ);
-
- avgBusLat
- .name(name() + ".avgBusLat")
- .desc("Average bus latency per DRAM burst")
- .precision(2);
+ System *sys = dram._system;
+ assert(sys);
+ const auto max_masters = dram._system->maxMasters();
- avgBusLat = totBusLat / (readBursts - servicedByWrQ);
+ perBankRdBursts.init(dram.banksPerRank * dram.ranksPerChannel);
+ perBankWrBursts.init(dram.banksPerRank * dram.ranksPerChannel);
- avgMemAccLat
- .name(name() + ".avgMemAccLat")
- .desc("Average memory access latency per DRAM burst")
- .precision(2);
+ avgRdQLen.precision(2);
+ avgWrQLen.precision(2);
+ avgQLat.precision(2);
+ avgBusLat.precision(2);
+ avgMemAccLat.precision(2);
- avgMemAccLat = totMemAccLat / (readBursts - servicedByWrQ);
+ readRowHitRate.precision(2);
+ writeRowHitRate.precision(2);
- numRdRetry
- .name(name() + ".numRdRetry")
- .desc("Number of times read queue was full causing retry");
+ readPktSize.init(ceilLog2(dram.burstSize) + 1);
+ writePktSize.init(ceilLog2(dram.burstSize) + 1);
- numWrRetry
- .name(name() + ".numWrRetry")
- .desc("Number of times write queue was full causing retry");
-
- readRowHits
- .name(name() + ".readRowHits")
- .desc("Number of row buffer hits during reads");
-
- writeRowHits
- .name(name() + ".writeRowHits")
- .desc("Number of row buffer hits during writes");
-
- readRowHitRate
- .name(name() + ".readRowHitRate")
- .desc("Row buffer hit rate for reads")
- .precision(2);
+ rdQLenPdf.init(dram.readBufferSize);
+ wrQLenPdf.init(dram.writeBufferSize);
- readRowHitRate = (readRowHits / (readBursts - servicedByWrQ)) * 100;
-
- writeRowHitRate
- .name(name() + ".writeRowHitRate")
- .desc("Row buffer hit rate for writes")
- .precision(2);
-
- writeRowHitRate = (writeRowHits / (writeBursts - mergedWrBursts)) * 100;
-
- readPktSize
- .init(ceilLog2(burstSize) + 1)
- .name(name() + ".readPktSize")
- .desc("Read request sizes (log2)");
-
- writePktSize
- .init(ceilLog2(burstSize) + 1)
- .name(name() + ".writePktSize")
- .desc("Write request sizes (log2)");
-
- rdQLenPdf
- .init(readBufferSize)
- .name(name() + ".rdQLenPdf")
- .desc("What read queue length does an incoming req see");
-
- wrQLenPdf
- .init(writeBufferSize)
- .name(name() + ".wrQLenPdf")
- .desc("What write queue length does an incoming req see");
-
- bytesPerActivate
- .init(maxAccessesPerRow ? maxAccessesPerRow : rowBufferSize)
- .name(name() + ".bytesPerActivate")
- .desc("Bytes accessed per row activation")
- .flags(nozero);
-
- rdPerTurnAround
- .init(readBufferSize)
- .name(name() + ".rdPerTurnAround")
- .desc("Reads before turning the bus around for writes")
- .flags(nozero);
-
- wrPerTurnAround
- .init(writeBufferSize)
- .name(name() + ".wrPerTurnAround")
- .desc("Writes before turning the bus around for reads")
- .flags(nozero);
-
- bytesReadDRAM
- .name(name() + ".bytesReadDRAM")
- .desc("Total number of bytes read from DRAM");
-
- bytesReadWrQ
- .name(name() + ".bytesReadWrQ")
- .desc("Total number of bytes read from write queue");
-
- bytesWritten
- .name(name() + ".bytesWritten")
- .desc("Total number of bytes written to DRAM");
-
- bytesReadSys
- .name(name() + ".bytesReadSys")
- .desc("Total read bytes from the system interface side");
-
- bytesWrittenSys
- .name(name() + ".bytesWrittenSys")
- .desc("Total written bytes from the system interface side");
-
- avgRdBW
- .name(name() + ".avgRdBW")
- .desc("Average DRAM read bandwidth in MiByte/s")
- .precision(2);
-
- avgRdBW = (bytesReadDRAM / 1000000) / simSeconds;
-
- avgWrBW
- .name(name() + ".avgWrBW")
- .desc("Average achieved write bandwidth in MiByte/s")
- .precision(2);
-
- avgWrBW = (bytesWritten / 1000000) / simSeconds;
-
- avgRdBWSys
- .name(name() + ".avgRdBWSys")
- .desc("Average system read bandwidth in MiByte/s")
- .precision(2);
-
- avgRdBWSys = (bytesReadSys / 1000000) / simSeconds;
-
- avgWrBWSys
- .name(name() + ".avgWrBWSys")
- .desc("Average system write bandwidth in MiByte/s")
- .precision(2);
-
- avgWrBWSys = (bytesWrittenSys / 1000000) / simSeconds;
-
- peakBW
- .name(name() + ".peakBW")
- .desc("Theoretical peak bandwidth in MiByte/s")
- .precision(2);
-
- peakBW = (SimClock::Frequency / tBURST) * burstSize / 1000000;
-
- busUtil
- .name(name() + ".busUtil")
- .desc("Data bus utilization in percentage")
- .precision(2);
- busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
-
- totGap
- .name(name() + ".totGap")
- .desc("Total gap between requests");
-
- avgGap
- .name(name() + ".avgGap")
- .desc("Average gap between requests")
- .precision(2);
-
- avgGap = totGap / (readReqs + writeReqs);
-
- // Stats for DRAM Power calculation based on Micron datasheet
- busUtilRead
- .name(name() + ".busUtilRead")
- .desc("Data bus utilization in percentage for reads")
- .precision(2);
-
- busUtilRead = avgRdBW / peakBW * 100;
-
- busUtilWrite
- .name(name() + ".busUtilWrite")
- .desc("Data bus utilization in percentage for writes")
- .precision(2);
+ bytesPerActivate
+ .init(dram.maxAccessesPerRow ?
+ dram.maxAccessesPerRow : dram.rowBufferSize)
+ .flags(nozero);
- busUtilWrite = avgWrBW / peakBW * 100;
+ rdPerTurnAround
+ .init(dram.readBufferSize)
+ .flags(nozero);
+ wrPerTurnAround
+ .init(dram.writeBufferSize)
+ .flags(nozero);
- pageHitRate
- .name(name() + ".pageHitRate")
- .desc("Row buffer hit rate, read and write combined")
- .precision(2);
+ avgRdBW.precision(2);
+ avgWrBW.precision(2);
+ avgRdBWSys.precision(2);
+ avgWrBWSys.precision(2);
+ peakBW.precision(2);
+ busUtil.precision(2);
+ avgGap.precision(2);
+ busUtilWrite.precision(2);
+ pageHitRate.precision(2);
- pageHitRate = (writeRowHits + readRowHits) /
- (writeBursts - mergedWrBursts + readBursts - servicedByWrQ) * 100;
// per-master bytes read and written to memory
masterReadBytes
- .init(_system->maxMasters())
- .name(name() + ".masterReadBytes")
- .desc("Per-master bytes read from memory")
+ .init(max_masters)
.flags(nozero | nonan);
masterWriteBytes
- .init(_system->maxMasters())
- .name(name() + ".masterWriteBytes")
- .desc("Per-master bytes write to memory")
+ .init(max_masters)
.flags(nozero | nonan);
// per-master bytes read and written to memory rate
- masterReadRate.name(name() + ".masterReadRate")
- .desc("Per-master bytes read from memory rate (Bytes/sec)")
+ masterReadRate
.flags(nozero | nonan)
.precision(12);
- masterReadRate = masterReadBytes/simSeconds;
-
- masterWriteRate
- .name(name() + ".masterWriteRate")
- .desc("Per-master bytes write to memory rate (Bytes/sec)")
- .flags(nozero | nonan)
- .precision(12);
-
- masterWriteRate = masterWriteBytes/simSeconds;
-
masterReadAccesses
- .init(_system->maxMasters())
- .name(name() + ".masterReadAccesses")
- .desc("Per-master read serviced memory accesses")
+ .init(max_masters)
.flags(nozero);
masterWriteAccesses
- .init(_system->maxMasters())
- .name(name() + ".masterWriteAccesses")
- .desc("Per-master write serviced memory accesses")
+ .init(max_masters)
.flags(nozero);
-
masterReadTotalLat
- .init(_system->maxMasters())
- .name(name() + ".masterReadTotalLat")
- .desc("Per-master read total memory access latency")
+ .init(max_masters)
.flags(nozero | nonan);
- masterReadAvgLat.name(name() + ".masterReadAvgLat")
- .desc("Per-master read average memory access latency")
+ masterReadAvgLat
.flags(nonan)
.precision(2);
- masterReadAvgLat = masterReadTotalLat/masterReadAccesses;
+
+ busUtilRead
+ .precision(2);
+
+ masterWriteRate
+ .flags(nozero | nonan)
+ .precision(12);
masterWriteTotalLat
- .init(_system->maxMasters())
- .name(name() + ".masterWriteTotalLat")
- .desc("Per-master write total memory access latency")
+ .init(max_masters)
.flags(nozero | nonan);
- masterWriteAvgLat.name(name() + ".masterWriteAvgLat")
- .desc("Per-master write average memory access latency")
+ masterWriteAvgLat
.flags(nonan)
.precision(2);
- masterWriteAvgLat = masterWriteTotalLat/masterWriteAccesses;
-
- for (int i = 0; i < _system->maxMasters(); i++) {
- const std::string master = _system->getMasterName(i);
+ for (int i = 0; i < max_masters; i++) {
+ const std::string master = dram._system->getMasterName(i);
masterReadBytes.subname(i, master);
masterReadRate.subname(i, master);
masterWriteBytes.subname(i, master);
@@ -2838,6 +2639,96 @@ DRAMCtrl::regStats()
masterWriteTotalLat.subname(i, master);
masterWriteAvgLat.subname(i, master);
}
+
+ // Formula stats
+ avgQLat = totQLat / (readBursts - servicedByWrQ);
+ avgBusLat = totBusLat / (readBursts - servicedByWrQ);
+ avgMemAccLat = totMemAccLat / (readBursts - servicedByWrQ);
+
+ readRowHitRate = (readRowHits / (readBursts - servicedByWrQ)) * 100;
+ writeRowHitRate = (writeRowHits / (writeBursts - mergedWrBursts)) * 100;
+
+ avgRdBW = (bytesReadDRAM / 1000000) / simSeconds;
+ avgWrBW = (bytesWritten / 1000000) / simSeconds;
+ avgRdBWSys = (bytesReadSys / 1000000) / simSeconds;
+ avgWrBWSys = (bytesWrittenSys / 1000000) / simSeconds;
+ peakBW = (SimClock::Frequency / dram.tBURST) * dram.burstSize / 1000000;
+
+ busUtil = (avgRdBW + avgWrBW) / peakBW * 100;
+
+ avgGap = totGap / (readReqs + writeReqs);
+
+ busUtilRead = avgRdBW / peakBW * 100;
+ busUtilWrite = avgWrBW / peakBW * 100;
+
+ pageHitRate = (writeRowHits + readRowHits) /
+ (writeBursts - mergedWrBursts + readBursts - servicedByWrQ) * 100;
+
+ masterReadRate = masterReadBytes / simSeconds;
+ masterWriteRate = masterWriteBytes / simSeconds;
+ masterReadAvgLat = masterReadTotalLat / masterReadAccesses;
+ masterWriteAvgLat = masterWriteTotalLat / masterWriteAccesses;
+}
+
+void
+DRAMCtrl::DRAMStats::resetStats()
+{
+ dram.lastStatsResetTick = curTick();
+}
+
+DRAMCtrl::RankStats::RankStats(DRAMCtrl &_memory, Rank &_rank)
+ : Stats::Group(&_memory, csprintf("rank%d", _rank.rank).c_str()),
+ rank(_rank),
+
+ ADD_STAT(actEnergy, "Energy for activate commands per rank (pJ)"),
+ ADD_STAT(preEnergy, "Energy for precharge commands per rank (pJ)"),
+ ADD_STAT(readEnergy, "Energy for read commands per rank (pJ)"),
+ ADD_STAT(writeEnergy, "Energy for write commands per rank (pJ)"),
+ ADD_STAT(refreshEnergy, "Energy for refresh commands per rank (pJ)"),
+ ADD_STAT(actBackEnergy, "Energy for active background per rank (pJ)"),
+ ADD_STAT(preBackEnergy, "Energy for precharge background per rank (pJ)"),
+ ADD_STAT(actPowerDownEnergy,
+ "Energy for active power-down per rank (pJ)"),
+ ADD_STAT(prePowerDownEnergy,
+ "Energy for precharge power-down per rank (pJ)"),
+ ADD_STAT(selfRefreshEnergy, "Energy for self refresh per rank (pJ)"),
+
+ ADD_STAT(totalEnergy, "Total energy per rank (pJ)"),
+ ADD_STAT(averagePower, "Core power per rank (mW)"),
+
+ ADD_STAT(totalIdleTime, "Total Idle time Per DRAM Rank"),
+ ADD_STAT(memoryStateTime, "Time in different power states")
+{
+}
+
+void
+DRAMCtrl::RankStats::regStats()
+{
+ Stats::Group::regStats();
+
+ memoryStateTime.init(6);
+ memoryStateTime.subname(0, "IDLE");
+ memoryStateTime.subname(1, "REF");
+ memoryStateTime.subname(2, "SREF");
+ memoryStateTime.subname(3, "PRE_PDN");
+ memoryStateTime.subname(4, "ACT");
+ memoryStateTime.subname(5, "ACT_PDN");
+}
+
+void
+DRAMCtrl::RankStats::resetStats()
+{
+ Stats::Group::resetStats();
+
+ rank.resetStats();
+}
+
+void
+DRAMCtrl::RankStats::preDumpStats()
+{
+ Stats::Group::preDumpStats();
+
+ rank.computeStats();
}
void