summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNeha Agarwal <neha.agarwal@arm.com>2013-11-01 11:56:28 -0400
committerNeha Agarwal <neha.agarwal@arm.com>2013-11-01 11:56:28 -0400
commit5c486908d7979e4be832700ddeadb43c172c84e1 (patch)
tree7d5e87efe0c653a4388c4c15e48e37ed5d4084ec /src
parent77fce1ce0e1db502b47ea72c4243c929666d04fa (diff)
downloadgem5-5c486908d7979e4be832700ddeadb43c172c84e1.tar.xz
mem: Adding stats for DRAM power calculation
This patch adds stats which are used for offline power calculation from the 'Micron Power Calculator' spreadsheet.
Diffstat (limited to 'src')
-rw-r--r--src/mem/simple_dram.cc82
-rw-r--r--src/mem/simple_dram.hh15
2 files changed, 88 insertions, 9 deletions
diff --git a/src/mem/simple_dram.cc b/src/mem/simple_dram.cc
index 46e81f564..b05773f0d 100644
--- a/src/mem/simple_dram.cc
+++ b/src/mem/simple_dram.cc
@@ -79,7 +79,8 @@ SimpleDRAM::SimpleDRAM(const SimpleDRAMParams* p) :
backendLatency(p->static_backend_latency),
busBusyUntil(0), writeStartTime(0),
prevArrival(0), numReqs(0),
- numWritesThisTime(0), newTime(0)
+ numWritesThisTime(0), newTime(0),
+ startTickPrechargeAll(0), numBanksActive(0)
{
// create the bank states based on the dimensions of the ranks and
// banks
@@ -327,7 +328,7 @@ SimpleDRAM::addToReadQueue(PacketPtr pkt, unsigned int pktCount)
pktsServicedByWrQ++;
DPRINTF(DRAM, "Read to addr %lld with size %d serviced by "
"write queue\n", addr, size);
- bytesRead += burstSize;
+ bytesReadWrQ += burstSize;
bytesConsumedRd += size;
break;
}
@@ -728,7 +729,7 @@ SimpleDRAM::processRespondEvent()
// Actually responds to the requestor
bytesConsumedRd += dram_pkt->size;
- bytesRead += burstSize;
+ bytesReadDRAM += burstSize;
if (dram_pkt->burstHelper) {
// it is a split packet
dram_pkt->burstHelper->burstsServiced++;
@@ -995,6 +996,21 @@ SimpleDRAM::recordActivate(Tick act_tick, uint8_t rank, uint8_t bank)
DPRINTF(DRAM, "Activate at tick %d\n", act_tick);
+ // Tracking accesses after all banks are precharged.
+ // startTickPrechargeAll: is the tick when all the banks were again
+ // precharged. The difference between act_tick and startTickPrechargeAll
+ // gives the time for which DRAM doesn't get any accesses after refreshing
+ // or after a page is closed in closed-page or open-adaptive-page policy.
+ if ((numBanksActive == 0) && (act_tick > startTickPrechargeAll)) {
+ prechargeAllTime += act_tick - startTickPrechargeAll;
+ }
+
+ // No need to update number of active banks for closed-page policy as only 1
+ // bank will be activated at any given point, which will be instatntly
+ // precharged
+ if (pageMgmt == Enums::open || pageMgmt == Enums::open_adaptive)
+ ++numBanksActive;
+
// start by enforcing tRRD
for(int i = 0; i < banksPerRank; i++) {
// next activate must not happen before tRRD
@@ -1111,6 +1127,14 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
if (!got_more_hits && got_bank_conflict) {
bank.openRow = -1;
bank.freeAt = std::max(bank.freeAt, bank.tRASDoneAt) + tRP;
+ --numBanksActive;
+ if (numBanksActive == 0) {
+ startTickPrechargeAll = std::max(startTickPrechargeAll,
+ bank.freeAt);
+ DPRINTF(DRAM, "All banks precharged at tick: %ld\n",
+ startTickPrechargeAll);
+ }
+ DPRINTF(DRAM, "Auto-precharged bank: %d\n", dram_pkt->bankId);
}
}
@@ -1126,6 +1150,7 @@ SimpleDRAM::doDRAMAccess(DRAMPacket* dram_pkt)
actTick + tRCD + tCL + tRP);
DPRINTF(DRAM, "doDRAMAccess::bank.freeAt is %lld\n", bank.freeAt);
bytesPerActivate.sample(burstSize);
+ startTickPrechargeAll = std::max(startTickPrechargeAll, bank.freeAt);
} else
panic("No page management policy chosen\n");
@@ -1302,8 +1327,14 @@ SimpleDRAM::processRefreshEvent()
Tick banksFree = std::max(curTick(), maxBankFreeAt()) + tRFC;
for(int i = 0; i < ranksPerChannel; i++)
- for(int j = 0; j < banksPerRank; j++)
+ for(int j = 0; j < banksPerRank; j++) {
banks[i][j].freeAt = banksFree;
+ banks[i][j].openRow = -1;
+ }
+
+ // updating startTickPrechargeAll, isprechargeAll
+ numBanksActive = 0;
+ startTickPrechargeAll = banksFree;
schedule(refreshEvent, curTick() + tREFI);
}
@@ -1463,9 +1494,13 @@ SimpleDRAM::regStats()
.desc("Bytes accessed per row activation")
.flags(nozero);
- bytesRead
- .name(name() + ".bytesRead")
- .desc("Total number of bytes read from memory");
+ 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")
@@ -1484,7 +1519,7 @@ SimpleDRAM::regStats()
.desc("Average achieved read bandwidth in MB/s")
.precision(2);
- avgRdBW = (bytesRead / 1000000) / simSeconds;
+ avgRdBW = ((bytesReadDRAM + bytesReadWrQ) / 1000000) / simSeconds;
avgWrBW
.name(name() + ".avgWrBW")
@@ -1531,6 +1566,37 @@ SimpleDRAM::regStats()
.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);
+
+ busUtilWrite = avgWrBW / peakBW * 100;
+
+ pageHitRate
+ .name(name() + ".pageHitRate")
+ .desc("Row buffer hit rate, read and write combined")
+ .precision(2);
+
+ pageHitRate = (writeRowHits + readRowHits) / (writeReqs + readReqs -
+ servicedByWrQ) * 100;
+
+ prechargeAllPercent
+ .name(name() + ".prechargeAllPercent")
+ .desc("Percentage of time for which DRAM has all the banks in "
+ "precharge state")
+ .precision(2);
+
+ prechargeAllPercent = prechargeAllTime / simTicks * 100;
}
void
diff --git a/src/mem/simple_dram.hh b/src/mem/simple_dram.hh
index 535e3a8c5..175c415d6 100644
--- a/src/mem/simple_dram.hh
+++ b/src/mem/simple_dram.hh
@@ -544,7 +544,8 @@ class SimpleDRAM : public AbstractMemory
Stats::Scalar writeReqs;
Stats::Scalar readBursts;
Stats::Scalar writeBursts;
- Stats::Scalar bytesRead;
+ Stats::Scalar bytesReadDRAM;
+ Stats::Scalar bytesReadWrQ;
Stats::Scalar bytesWritten;
Stats::Scalar bytesConsumedRd;
Stats::Scalar bytesConsumedWr;
@@ -580,6 +581,8 @@ class SimpleDRAM : public AbstractMemory
Stats::Formula avgConsumedWrBW;
Stats::Formula peakBW;
Stats::Formula busUtil;
+ Stats::Formula busUtilRead;
+ Stats::Formula busUtilWrite;
// Average queue lengths
Stats::Average avgRdQLen;
@@ -592,6 +595,16 @@ class SimpleDRAM : public AbstractMemory
Stats::Formula writeRowHitRate;
Stats::Formula avgGap;
+ // DRAM Power Calculation
+ Stats::Formula pageHitRate;
+ Stats::Formula prechargeAllPercent;
+ Stats::Scalar prechargeAllTime;
+
+ // To track number of cycles all the banks are precharged
+ Tick startTickPrechargeAll;
+ // To track number of banks which are currently active
+ unsigned int numBanksActive;
+
/** @todo this is a temporary workaround until the 4-phase code is
* committed. upstream caches needs this packet until true is returned, so
* hold onto it for deletion until a subsequent call