diff options
author | Andreas Sandberg <andreas.sandberg@arm.com> | 2019-09-23 18:20:23 +0100 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2019-09-30 12:33:47 +0000 |
commit | 76384ec3ff2a52898aa35a27d337194ae557648a (patch) | |
tree | f403d38cb5fb050b60f5299d60d908abc504ecf4 /src/mem/dram_ctrl.cc | |
parent | a060ac86307311587d05d280ee1f4cbdb84fe98a (diff) | |
download | gem5-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.cc | 711 |
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 |