ext: Update DRAMPower
authorMatthias Jung <jungma@eit.uni-kl.de>
Fri, 1 Jul 2016 15:31:36 +0000 (10:31 -0500)
committerMatthias Jung <jungma@eit.uni-kl.de>
Fri, 1 Jul 2016 15:31:36 +0000 (10:31 -0500)
Sync DRAMPower to external tool

This patch syncs the DRAMPower library of gem5 to the external
one on github (https://github.com/ravenrd/DRAMPower) of which
I am a maintainer.

The version used is the commit:
902a00a1797c48a9df97ec88868f20e847680ae6
from 07.  May.  2016.

Committed by Jason Lowe-Power <jason@lowepower.com>

19 files changed:
ext/drampower/README.md
ext/drampower/src/CmdScheduler.cc
ext/drampower/src/CmdScheduler.h
ext/drampower/src/CommandAnalysis.cc
ext/drampower/src/CommandAnalysis.h
ext/drampower/src/MemArchitectureSpec.h
ext/drampower/src/MemCommand.cc
ext/drampower/src/MemCommand.h
ext/drampower/src/MemTimingSpec.h
ext/drampower/src/MemoryPowerModel.cc
ext/drampower/src/MemoryPowerModel.h
ext/drampower/src/MemorySpecification.h
ext/drampower/src/TraceParser.cc
ext/drampower/src/TraceParser.h
ext/drampower/src/Utils.h
ext/drampower/src/libdrampower/LibDRAMPower.cc
ext/drampower/src/libdrampower/LibDRAMPower.h
ext/drampower/test/libdrampowertest/lib_test.cc
src/mem/dram_ctrl.hh

index a43298b01b6ff138f246b6509e3e34a7566a108b..5d6eb6e82a1f322391deb85fdc3722ba06b0a4b9 100644 (file)
@@ -252,8 +252,8 @@ The tool is based on the DRAM power model developed jointly by the Computer Engi
 
 **To cite the DRAMPower Tool:**
 ```
-[1] "DRAMPower: Open-source DRAM power & energy estimation tool"
-Karthik Chandrasekar, Christian Weis, Yonghui Li, Benny Akesson, Norbert Wehn, and Kees Goossens
+[1] DRAMPower: Open-source DRAM Power & Energy Estimation Tool
+Karthik Chandrasekar, Christian Weis, Yonghui Li, Sven Goossens, Matthias Jung, Omar Naji, Benny Akesson, Norbert Wehn, and Kees Goossens
 URL: http://www.drampower.info
 ```
 
index bffc5d3bbde1ca36defc54100a60dc81081983c8..a4619b94ecb712ba948f9ea5ff2eb2f119a725fe 100644 (file)
@@ -31,7 +31,7 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Karthik Chandrasekar
+ * Authors: Karthik Chandrasekar, Yonghui Li, Sven Goossens
  *
  */
 #include "CmdScheduler.h"
 #include <algorithm>  // For max
 
 
+#define MILLION 1000000
+
+
 using namespace std;
 using namespace Data;
 
 // Read the traces and get the transaction. Each transaction is executed by
 // scheduling a number of commands to the memory. Hence, the transactions are
 // translated into a sequence of commands which will be used for power analysis.
-void cmdScheduler::transTranslation(MemorySpecification memSpec,
+void cmdScheduler::transTranslation(const MemorySpecification& memSpec,
                                     ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
 {
   commands.open("commands.trace", ifstream::out);
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
   nBanks          = memArchSpec.nbrOfBanks;
   nColumns        = memArchSpec.nbrOfColumns;
   burstLength     = memArchSpec.burstLength;
@@ -77,13 +80,14 @@ void cmdScheduler::transTranslation(MemorySpecification memSpec,
 } // cmdScheduler::transTranslation
 
 // initialize the variables and vectors for starting command scheduling.
-void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
+void cmdScheduler::schedulingInitialization(const MemorySpecification& memSpec)
 {
-  MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
+  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
 
-  ACT.resize(2 * memSpec.memArchSpec.nbrOfBanks);
-  RDWR.resize(2 * memSpec.memArchSpec.nbrOfBanks);
-  PRE.resize(memSpec.memArchSpec.nbrOfBanks);
+  const size_t numBanks = static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks);
+  ACT.resize(2 * numBanks);
+  RDWR.resize(2 * numBanks);
+  PRE.resize(numBanks);
   bankaccess = memSpec.memArchSpec.nbrOfBanks;
   if (!ACT.empty()) {
     ACT.erase(ACT.begin(), ACT.end());
@@ -96,14 +100,15 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
   }
 
   ///////////////initialization//////////////
-  for (unsigned i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
+  for (int64_t i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
     cmd.Type = PRECHARGE;
-    cmd.bank = i;
+    cmd.bank = static_cast<unsigned>(i);
     cmd.name = "PRE";
-    if (memSpec.id == "WIDEIO_SDR")
-      cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.TAW);
-    else
-      cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.FAW);
+    if (memSpec.id == "WIDEIO_SDR") {
+      cmd.time = 1 - memSpec.memTimingSpec.TAW;
+    } else {
+      cmd.time = 1 - memSpec.memTimingSpec.FAW;
+    }
 
     PRE.push_back(cmd);
 
@@ -114,7 +119,7 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
     cmd.Type = WRITE;
     cmd.name = "WRITE";
     cmd.time = -1;
-    RDWR[i].push_back(cmd);
+    RDWR[static_cast<size_t>(i)].push_back(cmd);
   }
   tREF             = memTimingSpec.REFI;
   transFinish.time = 0;
@@ -130,14 +135,14 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
 // transactions are generated according to the information read from the traces.
 // Then the command scheduling function is triggered to generate commands and
 // schedule them to the memory according to the timing constraints.
-void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memSpec)
+void cmdScheduler::getTrans(std::ifstream& trans_trace, const MemorySpecification& memSpec)
 {
   std::string line;
 
   transTime = 0;
-  unsigned newtranstime;
-  unsigned transAddr;
-  unsigned transType = 1;
+  uint64_t newtranstime;
+  uint64_t transAddr;
+  int64_t transType = 1;
   trans    TransItem;
 
   if (!transTrace.empty()) {
@@ -147,12 +152,12 @@ void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memS
   while (getline(trans_trace, line)) {
     istringstream linestream(line);
     string item;
-    unsigned itemnum = 0;
+    uint64_t itemnum = 0;
     while (getline(linestream, item, ',')) {
       if (itemnum == 0) {
         stringstream timestamp(item);
         timestamp >> newtranstime;
-        transTime = transTime + newtranstime;
+        transTime = transTime + static_cast<int64_t>(newtranstime);
       } else if (itemnum == 1) {
         if (item  == "write" || item == "WRITE") {
           transType = WRITE;
@@ -191,33 +196,35 @@ void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memS
 // be scheduled until all the commands for the current one are scheduled.
 // After the scheduling, a sequence of commands are obtained and they are written
 // into commands.txt which will be used for power analysis.
-void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
+void cmdScheduler::analyticalScheduling(const MemorySpecification& memSpec)
 {
-  int  Bs               = -1;
-  int  transType        = -1;
-  double timer          = 0;
-  int  bankGroupPointer = 0;
-  int  bankGroupAddr    = 0;
+  int64_t  transType        = -1;
+  int64_t timer          = 0;
+  uint64_t  bankGroupPointer = 0;
+  uint64_t  bankGroupAddr    = 0;
   bool collisionFound;
   physicalAddr PhysicalAddress;
   bool bankGroupSwitch  = false;
-  std::vector<unsigned> bankPointer(nbrOfBankGroups, 0);
-  std::vector<int>  bankAccessNum(nBanks, -1);
-  std::vector<bool> ACTSchedule(nBanks, false);
-  int bankAddr       = -1;
-  double endTime     = 0;
-  double tComing_REF = 0;
+  std::vector<uint64_t> bankPointer(static_cast<size_t>(nbrOfBankGroups), 0);
+  std::vector<int64_t>  bankAccessNum(static_cast<size_t>(nBanks), -1);
+  std::vector<bool> ACTSchedule(static_cast<size_t>(nBanks), false);
+  uint64_t bankAddr   = 0;
+  int64_t endTime     = 0;
+  int64_t tComing_REF = 0;
 
   Inselfrefresh = 0;
 
-  MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
+  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
 
-  for (unsigned t = 0; t < transTrace.size(); t++) {
+  for (uint64_t t = 0; t < transTrace.size(); t++) {
     cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
 
-    for (unsigned i = 0; i < nBanks; i++) {
-      ACTSchedule[i]   = false;
-      bankAccessNum[i] = -1;
+    for (auto a : ACTSchedule) {
+      a = false;
+    }
+
+    for (auto& b : bankAccessNum) {
+      b = -1;
     }
 
     timingsGet      = false;
@@ -225,13 +232,13 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
 
     PhysicalAddress = memoryMap(transTrace[t], memSpec);
 
-    for (unsigned i = 0; i < nbrOfBankGroups; i++) {
-      bankPointer[i] = PhysicalAddress.bankAddr; // the bank pointer per group.
+    for (auto& b : bankPointer) {
+      b = PhysicalAddress.bankAddr; // the bank pointer per group.
     }
     bankGroupPointer = PhysicalAddress.bankGroupAddr;
 
-    endTime          = max(transFinish.time, PRE[transFinish.bank].time +
-                           static_cast<int>(memTimingSpec.RP));
+    endTime = max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time +
+                                    static_cast<int>(memTimingSpec.RP));
 
     // Before starting the scheduling for the next transaction, it has to
     // check whether it is necessary for implementing power down.
@@ -244,14 +251,12 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
 
     ///////////////Scheduling Refresh////////////////////////
     if (((transFinish.time >= tREF) || (timer >= tREF))) {
-      for (double i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
+      for (int64_t i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
                                memTimingSpec.REFI : 0); i++) {
         cmd.bank = 0;
         cmd.name = "REF";
-        cmd.time = max(max(max(transFinish.time, PRE[transFinish.bank].time
-                               + static_cast<int>(memTimingSpec.RP)), tREF), startTime);
-        if (((power_down == SELF_REFRESH) && !Inselfrefresh) ||
-            (power_down != SELF_REFRESH)) {
+        cmd.time = max(max(max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time + memTimingSpec.RP), tREF), startTime);
+        if ((power_down == SELF_REFRESH && !Inselfrefresh) || power_down != SELF_REFRESH) {
           cmdScheduling.push_back(cmd);
           startTime = cmd.time + memTimingSpec.RFC;
         }
@@ -262,7 +267,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
       }
     }
     ///////////////Execution Transactions///////////////////
-    Bs        = PhysicalAddress.bankAddr;
+    uint64_t Bs = PhysicalAddress.bankAddr;
     transType = transTrace[t].type;
 
     tRWTP     = getRWTP(transType, memSpec);
@@ -280,9 +285,8 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
               bankGroupSwitch = true;
             }
             // update to the current bank group address.
-            bankGroupAddr = PhysicalAddress.bankGroupAddr + j;
-            bankAddr      = bankGroupAddr * nBanks / nbrOfBankGroups +
-                            bankPointer[bankGroupAddr];
+            bankGroupAddr = PhysicalAddress.bankGroupAddr + static_cast<uint64_t>(j);
+            bankAddr = bankGroupAddr * static_cast<uint64_t>(nBanks) / nbrOfBankGroups + bankPointer[bankGroupAddr];
           } else   {
             bankAddr = Bs + i;
           }
@@ -312,7 +316,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
                              static_cast<int>(memTimingSpec.TAW));
             }
 
-            if ((i == 0) && (j == 0)) {
+            if (i == 0 && j == 0) {
               cmd.time = max(cmd.time, PreRDWR.time + 1);
               cmd.time = max(cmd.time, timer);
               cmd.time = max(startTime, cmd.time);
@@ -358,7 +362,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
           }
           for (int ACTBank = static_cast<int>(ACT.size() - 1);
                ACTBank >= 0; ACTBank--) {
-            if (ACT[ACTBank].bank == bankAddr) {
+            if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
               cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
                              + static_cast<int>(memTimingSpec.RCD));
               break;
@@ -392,7 +396,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
             PRE[bankAddr].name = "PRE";
             for (int ACTBank = static_cast<int>(ACT.size() - 1);
                  ACTBank >= 0; ACTBank--) {
-              if (ACT[ACTBank].bank == bankAddr) {
+              if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
                 PRE[bankAddr].time = max(ACT.back().time +
                                          static_cast<int>(memTimingSpec.RAS),
                                          PreRDWR.time + tRWTP);
@@ -419,7 +423,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
     /////////////Update Vector Length/////////////////
     // the vector length is reduced so that less memory is used for running
     // this tool.
-    if (ACT.size() >= memSpec.memArchSpec.nbrOfBanks) {
+    if (ACT.size() >= static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks)) {
       for (int m = 0; m < BI * BGI; m++) {
         ACT.erase(ACT.begin());
         RDWR[0].erase(RDWR[0].begin(), RDWR[0].end());
@@ -443,14 +447,14 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
 // to add the power down/up during the command scheduling for transactions.
 // It is called when the command scheduling for a transaction is finished, and it
 // is also called if there is a refresh.
-void cmdScheduler::pdScheduling(double endTime, double timer,
-                                MemorySpecification memSpec)
+void cmdScheduler::pdScheduling(int64_t endTime, int64_t timer,
+                                const MemorySpecification& memSpec)
 {
-  double ZERO = 0;
-  MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
+  int64_t ZERO = 0;
+  const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
 
   endTime = max(endTime, startTime);
-  double pdTime = max(ZERO, timer - endTime);
+  int64_t pdTime = max(ZERO, timer - endTime);
 
   if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
     cmd.bank = 0;
@@ -490,11 +494,11 @@ void cmdScheduler::pdScheduling(double endTime, double timer,
 
 // get the time when a precharge occurs after a read/write command is scheduled.
 // In addition, it copes with different kind of memories.
-int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
+int64_t cmdScheduler::getRWTP(int64_t transType, const MemorySpecification& memSpec)
 {
-  int tRWTP_init = 0;
-  MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  int64_t tRWTP_init = 0;
+  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
 
   if (transType == READ) {
     switch (memSpec.memoryType) {
@@ -506,13 +510,13 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
     case MemoryType::LPDDR2:
     case MemoryType::LPDDR3:
       tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
-                   max(0, static_cast<int>(memTimingSpec.RTP - 2));
+                   max(int64_t(0), memTimingSpec.RTP - 2);
       break;
 
     case MemoryType::DDR2:
       tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
                    memArchSpec.dataRate +
-                   max(static_cast<int>(memTimingSpec.RTP), 2) - 2;
+                   max(memTimingSpec.RTP, int64_t(2)) - 2;
       break;
 
     case MemoryType::DDR3:
@@ -525,10 +529,10 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
   } else if (transType == WRITE)    {
     if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
       tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
-                   memArchSpec.dataRate - 1 + memSpec.memTimingSpec.WR;
+                   memArchSpec.dataRate - 1 + memTimingSpec.WR;
     } else   {
       tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
-                   memArchSpec.dataRate + memSpec.memTimingSpec.WR;
+                   memArchSpec.dataRate + memTimingSpec.WR;
     }
     if ((memSpec.memoryType == MemoryType::LPDDR2) ||
         (memSpec.memoryType == MemoryType::LPDDR3)) {
@@ -543,11 +547,11 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
 // In particular, tSwitch_init is generally used to provide the timings for
 // scheduling a read/write command after a read/write command which have been
 // scheduled to any possible banks within any possible bank groups (DDR4).
-void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSpec,
-                                        int PreType, int CurrentType)
+void cmdScheduler::getTimingConstraints(bool BGSwitch, const MemorySpecification& memSpec,
+                                        int64_t PreType, int64_t CurrentType)
 {
-  MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
 
   if (memSpec.memoryType != MemoryType::DDR4) {
     tRRD_init = memTimingSpec.RRD;
@@ -586,7 +590,7 @@ void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSp
     if (PreType == CurrentType) {
       tSwitch_init = tCCD_init;
       timingsGet   = true;
-    } else if ((PreType == WRITE) && (CurrentType == READ)) {
+    } else if (PreType == WRITE && CurrentType == READ) {
       tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
                      memArchSpec.dataRate + tWTR_init;
     }
@@ -601,59 +605,55 @@ void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSp
 // The logical address of each transaction is translated into a physical address
 // which consists of bank group (for DDR4), bank, row and column addresses.
 cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans               Trans,
-                                                   MemorySpecification memSpec)
+                                                   const MemorySpecification& memSpec)
 {
-  int DecLogic;
+  int64_t DecLogic;
   physicalAddr PhysicalAddr;
 
   DecLogic = Trans.logicalAddress;
 
   // row-bank-column-BI-BC-BGI-BL
-  if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) {
-    unsigned colBits   = static_cast<unsigned>(log2(nColumns));
-    unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)
-                                               + ((BGI > 1) ? log2(BGI) : 0));
-    unsigned bankMask  = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1)
-                        << bankShift;
-    unsigned bankAddr  = (DecLogic & bankMask) >>
-                         static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0));
+  if (BGI > 1 && memSpec.memoryType == MemoryType::DDR4) {
+    uint64_t colBits   = uintLog2(nColumns);
+    uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0)  + ((BGI > 1) ? uintLog2(BGI) : 0);
+    uint64_t bankMask  = (nBanks / (BI * nbrOfBankGroups) - 1) << bankShift;
+    uint64_t bankAddr  = (DecLogic & bankMask) >> (colBits + ((BGI > 1) ? uintLog2(BGI) : 0));
     PhysicalAddr.bankAddr = bankAddr;
 
-    unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength));
-    unsigned bankGroupMask  = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
-    unsigned bankGroupAddr  = (DecLogic & bankGroupMask) >> bankGroupShift;
+    uint64_t bankGroupShift = uintLog2(burstLength);
+    uint64_t bankGroupMask  = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
+    uint64_t bankGroupAddr  = (DecLogic & bankGroupMask) >> bankGroupShift;
     PhysicalAddr.bankGroupAddr = bankGroupAddr;
 
-    unsigned colShift       = static_cast<unsigned>(log2(BC * burstLength) +
-                                                    ((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0));
-    unsigned colMask        = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
-                       << colShift;
-    unsigned colAddr        = (DecLogic & colMask) >>
-                              static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
+    uint64_t colShift       = uintLog2(BC * burstLength) +
+                                                    ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
+    uint64_t colMask        = (nColumns / (BC * burstLength) - 1) << colShift;
+    uint64_t colAddr        = (DecLogic & colMask) >> (colShift - uintLog2(static_cast<uint64_t>(BC) * burstLength));
     PhysicalAddr.colAddr = colAddr;
   } else   {
-    unsigned colBits   = static_cast<unsigned>(log2(nColumns));
-    unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0));
-    unsigned bankMask  = static_cast<unsigned>(nBanks / BI - 1) << bankShift;
-    unsigned bankAddr  = (DecLogic & bankMask) >> colBits;
+    uint64_t colBits   = uintLog2(nColumns);
+    uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0);
+    uint64_t bankMask  = (nBanks / BI - 1) << bankShift;
+    uint64_t bankAddr  = (DecLogic & bankMask) >> colBits;
     PhysicalAddr.bankAddr = bankAddr;
 
-    unsigned colShift  = static_cast<unsigned>(log2(BC * burstLength) +
-                                               ((BI > 1) ? log2(BI) : 0));
-    unsigned colMask   = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
-                       << colShift;
-    unsigned colAddr   = (DecLogic & colMask) >>
-                         static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
+    uint64_t colShift  = (uintLog2(BC * burstLength) + ((BI > 1) ? uintLog2(BI) : 0));
+    uint64_t colMask   = (nColumns / (BC * burstLength) - 1) << colShift;
+    uint64_t colAddr   = (DecLogic & colMask) >> (colShift - uintLog2(BC * burstLength));
     PhysicalAddr.colAddr       = colAddr;
 
     PhysicalAddr.bankGroupAddr = 0;
   }
 
-  unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks));
-  unsigned rowMask  = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1)
-                     << rowShift;
-  unsigned rowAddr  = (DecLogic & rowMask) >> rowShift;
+  uint64_t rowShift = uintLog2(nColumns * nBanks);
+  uint64_t rowMask  = (memSpec.memArchSpec.nbrOfRows - 1) << rowShift;
+  uint64_t rowAddr  = (DecLogic & rowMask) >> rowShift;
   PhysicalAddr.rowAddr = rowAddr;
 
   return PhysicalAddr;
 } // cmdScheduler::memoryMap
+
+uint64_t cmdScheduler::uintLog2(uint64_t in)
+{
+  return static_cast<uint64_t>(log2(in));
+}
\ No newline at end of file
index 3c60ea8868372d191621f00e17df43251924f802..58efd279b108a34858da53d15682cc2889479db9 100644 (file)
@@ -59,9 +59,9 @@ class cmdScheduler {
   // the format of a transaction.
   class trans {
    public:
-    int type;
-    double timeStamp;
-    unsigned logicalAddress;
+    int64_t type;
+    int64_t timeStamp;
+    uint64_t logicalAddress;
   };
 
   std::vector<trans> transTrace; // to store the transactions.
@@ -69,18 +69,18 @@ class cmdScheduler {
   // the format of physical address.
   class physicalAddr {
    public:
-    unsigned rowAddr;
-    unsigned bankAddr;
-    unsigned bankGroupAddr;
-    unsigned colAddr;
+    uint64_t rowAddr;
+    uint64_t bankAddr;
+    uint64_t bankGroupAddr;
+    uint64_t colAddr;
   };
 
   // the format of a command.
   class commandItem {
    public:
-    int Type;
-    int bank;
-    double time;
+    int64_t Type;
+    int64_t bank;
+    int64_t time;
     std::string  name;
     physicalAddr PhysicalAddr;
     // sorting the commands according to their scheduling time.
@@ -107,11 +107,11 @@ class cmdScheduler {
   std::vector<commandItem> cmdScheduling;
   std::vector<commandItem> cmdList;
   unsigned elements;
-  int BI, BC, BGI;
+  int64_t BI, BC, BGI;
 
   // the function used to translate a transaction into a sequence of
   // commands which are scheduled to the memory.
-  void transTranslation(Data::MemorySpecification memSpec,
+  void transTranslation(const MemorySpecification& memSpec,
                         std::ifstream&            trans_trace,
                         int                       grouping,
                         int                       interleaving,
@@ -119,45 +119,47 @@ class cmdScheduler {
                         int                       powerdown);
   // get the transactions by reading the traces.
   void getTrans(std::ifstream&      pwr_trace,
-                MemorySpecification memSpec);
+                const MemorySpecification& memSpec);
   // the initialization function for scheduling.
-  void schedulingInitialization(MemorySpecification memSpec);
+  void schedulingInitialization(const MemorySpecification& memSpec);
   // the function used to schedule commands according to the timing constraints.
-  void analyticalScheduling(MemorySpecification memSpec);
+  void analyticalScheduling(const MemorySpecification& memSpec);
   // translate the logical address into physical address.
   physicalAddr memoryMap(trans               Trans,
-                         MemorySpecification memSpec);
+                         const MemorySpecification& memSpec);
   // the power down and power up are scheduled by pdScheduling
-  void pdScheduling(double              endTime,
-                    double              timer,
-                    MemorySpecification memSpec);
+  void pdScheduling(int64_t endTime,
+                    int64_t timer,
+                    const MemorySpecification& memSpec);
   // get the timings for scheduling a precharge since a read or write command
   // is scheduled.
-  int getRWTP(int                 transType,
-              MemorySpecification memSpec);
+  int64_t getRWTP(int64_t transType,
+              const MemorySpecification& memSpec);
   // get different kind of timing constraints according to the used memory.
   void getTimingConstraints(bool                BGSwitch,
-                            MemorySpecification memSpec,
-                            int                 PreType,
-                            int                 CurrentType);
+                            const MemorySpecification& memSpec,
+                            int64_t                 PreType,
+                            int64_t                 CurrentType);
 
-  double transTime;
+  uint64_t uintLog2(uint64_t in);
+
+  int64_t transTime;
   // the flag for power down.
-  int    power_down;
-  int    Inselfrefresh;
-  int    tRRD_init;
-  int    tCCD_init;
-  int    tWTR_init;
-  double tREF;
-  double tSwitch_init;
-  double tRWTP;
-  int    bankaccess;
-  unsigned nBanks;
-  unsigned nColumns;
-  unsigned burstLength;
-  unsigned nbrOfBankGroups;
+  int64_t power_down;
+  int64_t Inselfrefresh;
+  int64_t tRRD_init;
+  int64_t tCCD_init;
+  int64_t tWTR_init;
+  int64_t tREF;
+  int64_t tSwitch_init;
+  int64_t tRWTP;
+  int64_t bankaccess;
+  int64_t nBanks;
+  int64_t nColumns;
+  int64_t burstLength;
+  int64_t nbrOfBankGroups;
   bool timingsGet;
-  double   startTime;
+  int64_t startTime;
 
   // the scheduling results for all the transactions are written into
   // commands which will be used by the power analysis part.
index 4dea5c101c298d04b77179f883fe933c3aba4e83..e557c2920577708f7c8ff82e3884d0d5d06790db 100644 (file)
 using namespace Data;
 using namespace std;
 
-CommandAnalysis::CommandAnalysis()
+bool commandSorter(const MemCommand& i, const MemCommand& j)
 {
+  if (i.getTimeInt64() == j.getTimeInt64()) {
+    return i.getType() == MemCommand::PRE && j.getType() != MemCommand::PRE;
+  } else {
+    return i.getTimeInt64() < j.getTimeInt64();
+  }
 }
 
-CommandAnalysis::CommandAnalysis(const int nbrofBanks)
+CommandAnalysis::CommandAnalysis(const int64_t nbrofBanks)
 {
   // Initializing all counters and variables
+  clearStats(0);
+  zero = 0;
+
+  bankstate.resize(static_cast<size_t>(nbrofBanks), 0);
+  last_states.resize(static_cast<size_t>(nbrofBanks));
+  mem_state  = 0;
+  num_active_banks  = 0;
+
+  cmd_list.clear();
+  cached_cmd.clear();
+  activation_cycle.resize(static_cast<size_t>(nbrofBanks), 0);
+}
+
+// function to clear counters
+void CommandAnalysis::clearStats(const int64_t timestamp)
+{
 
   numberofacts        = 0;
   numberofpres        = 0;
@@ -64,10 +85,6 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
   s_pre_pdns          = 0;
   numberofsrefs       = 0;
 
-  pop                 = 0;
-  init                = 0;
-  zero                = 0;
-
   actcycles           = 0;
   precycles           = 0;
   f_act_pdcycles      = 0;
@@ -85,28 +102,29 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
   idlecycles_act      = 0;
   idlecycles_pre      = 0;
 
+  // reset count references to timestamp so that they are moved
+  // to start of next stats generation
+  first_act_cycle     = timestamp;
+  last_pre_cycle      = timestamp;
+  pdn_cycle           = timestamp;
+  sref_cycle          = timestamp;
+  end_act_op          = timestamp;
+  end_read_op         = timestamp;
+  end_write_op        = timestamp;
+
   latest_act_cycle    = -1;
-  latest_pre_cycle    = -1;
   latest_read_cycle   = -1;
   latest_write_cycle  = -1;
-  end_read_op         = 0;
-  end_write_op        = 0;
-  end_act_op          = 0;
-
-  first_act_cycle     = 0;
-  last_pre_cycle      = 0;
 
-  bankstate.resize(nbrofBanks, 0);
-  last_states.resize(nbrofBanks);
-  mem_state  = 0;
-
-  sref_cycle = 0;
-  pdn_cycle  = 0;
-
-  cmd_list.clear();
-  full_cmd_list.resize(1, MemCommand::PRE);
-  cached_cmd.clear();
-  activation_cycle.resize(nbrofBanks, 0);
+  if (timestamp == 0) {
+    // set to -1 at beginning of simulation
+    latest_pre_cycle    = -1;
+  } else {
+    // NOTE: reference is adjusted by tRP (PRE delay) when updating counter
+    // could remove tRP to ensure counter starts at beginning of next block;
+    // currently simply setting to timestamp for simplicity
+    latest_pre_cycle    = timestamp;
+  }
 }
 
 // function to clear all arrays
@@ -114,7 +132,6 @@ void CommandAnalysis::clear()
 {
   cached_cmd.clear();
   cmd_list.clear();
-  full_cmd_list.clear();
   last_states.clear();
   bankstate.clear();
 }
@@ -125,132 +142,57 @@ void CommandAnalysis::clear()
 // issued command timestamp, when the auto-precharge would kick in
 
 void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
-                                  const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate)
+                                  std::vector<MemCommand>& list, bool lastupdate)
 {
-  for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) {
-    const MemCommand& cmd = *i;
-    cmd_list.push_back(cmd);
-
+  for (size_t i = 0; i < list.size(); ++i) {
+    MemCommand& cmd = list[i];
     MemCommand::cmds cmdType = cmd.getType();
     if (cmdType == MemCommand::ACT) {
       activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
     } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
       // Remove auto-precharge flag from command
-      cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag());
+      cmd.setType(cmd.typeWithoutAutoPrechargeFlag());
 
       // Add the auto precharge to the list of cached_cmds
       int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
                            activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
-      cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime)));
+      list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime));
     }
   }
-  pop = 0;
-  // Note: the extra pre-cmds at the end of the lists, and the cast to double
-  // of the size vector is probably not desirable.
-  cmd_list.push_back(MemCommand::PRE);
-  cached_cmd.push_back(MemCommand::PRE);
-  analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1,
-                                        cached_cmd.size()-1, lastupdate);
-  cmd_list.clear();
-  cached_cmd.clear();
-} // CommandAnalysis::getCommands
-
-// Checks the auto-precharge cached command list and inserts the explicit
-// precharges with the appropriate timestamp in the original command list
-// (by merging) based on their offset from the issuing command. Calls the
-// evaluate function to analyse this expanded list of commands.
+  sort(list.begin(), list.end(), commandSorter);
 
-void CommandAnalysis::analyse_commands(const int nbrofBanks,
-                                       Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate)
-{
-  full_cmd_list.resize(1, MemCommand::PRE);
-  unsigned mCommands = 0;
-  unsigned mCached   = 0;
-  for (unsigned i = 0; i < nCommands + nCached + 1; i++) {
-    if (cached_cmd.size() > 1) {
-      if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
-        full_cmd_list[i].setType(MemCommand::PREA);
-        init = 1;
-        pop  = 1;
-      } else {
-        init = 1;
-        if ((cached_cmd[mCached].getTime() > 0) && (cmd_list.
-                                                    at(mCommands).getTime() < cached_cmd[mCached].
-                                                    getTime()) && ((cmd_list[mCommands].getTime() > 0) ||
-                                                                   ((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands].
-                                                                                                             getType() != MemCommand::PRE)))) {
-          full_cmd_list[i] = cmd_list[mCommands];
-          mCommands++;
-        } else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands].
-                                                           getTime() >= cached_cmd[mCached].getTime())) {
-          full_cmd_list[i] = cached_cmd[mCached];
-          mCached++;
-        } else if (cached_cmd[mCached].getTime() == 0) {
-          if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands].
-                                                       getTime() == 0) && (cmd_list[mCommands].
-                                                                           getType() != MemCommand::PRE))) {
-            full_cmd_list[i] = cmd_list[mCommands];
-            mCommands++;
-          }
-        } else if (cmd_list[mCommands].getTime() == 0) {
-          full_cmd_list[i] = cached_cmd[mCached];
-          mCached++;
-        }
-      }
-    } else {
-      if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
-        full_cmd_list[i].setType(MemCommand::PREA);
-        init = 1;
-        pop  = 1;
-      } else {
-        init = 1;
-        if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list.
-                                                     at(mCommands).getTime() == 0) && (cmd_list[mCommands].
-                                                                                       getType() != MemCommand::PRE))) {
-          full_cmd_list[i] = cmd_list[mCommands];
-          mCommands++;
-        }
-      }
-    }
-    full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE);
+  if (lastupdate && list.empty() == false) {
+    // Add cycles at the end of the list
+    int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1;
+    list.push_back(MemCommand(MemCommand::NOP, 0, t));
   }
 
-  full_cmd_list.pop_back();
-  if (pop == 0) {
-    full_cmd_list.pop_back();
-  }
-  if (lastupdate) {
-    full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP);
-    full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list
-                                                    [full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec,
-                                                                                                            full_cmd_list[full_cmd_list.size() - 2].getType()) - 1);
-  }
+  evaluate(memSpec, list);
+} // CommandAnalysis::getCommands
 
-  evaluate(memSpec, full_cmd_list, nbrofBanks);
-} // CommandAnalysis::analyse_commands
 
 // To get the time of completion of the issued command
 // Derived based on JEDEC specifications
 
-int CommandAnalysis::timeToCompletion(const MemorySpecification&
+int64_t CommandAnalysis::timeToCompletion(const MemorySpecification&
                                       memSpec, MemCommand::cmds type)
 {
-  int offset = 0;
+  int64_t offset = 0;
   const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
   const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
 
   if (type == MemCommand::RD) {
-    offset = static_cast<int>(memTimingSpec.RL +
+    offset = memTimingSpec.RL +
                               memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
-                                                         memArchSpec.dataRate));
+                                                         memArchSpec.dataRate);
   } else if (type == MemCommand::WR) {
-    offset = static_cast<int>(memTimingSpec.WL +
+    offset = memTimingSpec.WL +
                               (memArchSpec.burstLength / memArchSpec.dataRate) +
-                              memTimingSpec.WR);
+                              memTimingSpec.WR;
   } else if (type == MemCommand::ACT) {
-    offset = static_cast<int>(memTimingSpec.RCD);
+    offset = memTimingSpec.RCD;
   } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
-    offset = static_cast<int>(memTimingSpec.RP);
+    offset = memTimingSpec.RP;
   }
   return offset;
 } // CommandAnalysis::timeToCompletion
@@ -258,38 +200,39 @@ int CommandAnalysis::timeToCompletion(const MemorySpecification&
 // Used to analyse a given list of commands and identify command timings
 // and memory state transitions
 void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
-                               vector<MemCommand>& cmd_list, int nbrofBanks)
+                               vector<MemCommand>& cmd_list)
 {
   // for each command identify timestamp, type and bank
-  for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size();
-       cmd_list_counter++) {
+  for (auto cmd : cmd_list) {
     // For command type
-    int type = cmd_list[cmd_list_counter].getType();
+    int type = cmd.getType();
     // For command bank
-    int bank = cmd_list[cmd_list_counter].getBank();
+    int bank = static_cast<int>(cmd.getBank());
     // Command Issue timestamp in clock cycles (cc)
-    int64_t timestamp = cmd_list[cmd_list_counter].getTimeInt64();
+    int64_t timestamp = cmd.getTimeInt64();
 
     if (type == MemCommand::ACT) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is ACT - update number of acts, bank state of the
       // target bank, first and latest activation cycle and the memory
       // state. Update the number of precharged/idle-precharged cycles.
       numberofacts++;
-      if (bankstate[bank] == 1) {
+      if (bankstate[static_cast<size_t>(bank)] == 1) {
         printWarning("Bank is already active!", type, timestamp, bank);
       }
-      bankstate[bank] = 1;
-      if (mem_state == 0) {
+      bankstate[static_cast<size_t>(bank)] = 1;
+      if (num_active_banks == 0) {
         first_act_cycle = timestamp;
         precycles      += max(zero, timestamp - last_pre_cycle);
         idle_pre_update(memSpec, timestamp, latest_pre_cycle);
       }
       latest_act_cycle = timestamp;
-      mem_state++;
+      num_active_banks++;
     } else if (type == MemCommand::RD) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is RD - update number of reads and read cycle. Check
       // for active idle cycles (if any).
-      if (bankstate[bank] == 0) {
+      if (bankstate[static_cast<size_t>(bank)] == 0) {
         printWarning("Bank is not active!", type, timestamp, bank);
       }
       numberofreads++;
@@ -297,9 +240,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
                       latest_act_cycle, timestamp);
       latest_read_cycle = timestamp;
     } else if (type == MemCommand::WR) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is WR - update number of writes and write cycle. Check
       // for active idle cycles (if any).
-      if (bankstate[bank] == 0) {
+      if (bankstate[static_cast<size_t>(bank)] == 0) {
         printWarning("Bank is not active!", type, timestamp, bank);
       }
       numberofwrites++;
@@ -307,6 +251,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
                       latest_act_cycle, timestamp);
       latest_write_cycle = timestamp;
     } else if (type == MemCommand::REF) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is REF - update number of refreshes, set bank state of
       // all banks to ACT, set the last PRE cycles at RFC-RP cycles from
       // timestamp, set the number of active cycles to RFC-RP and check
@@ -321,56 +266,54 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
                          memSpec.memTimingSpec.RP;
       latest_pre_cycle = last_pre_cycle;
       actcycles       += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
-      mem_state        = 0;
-      for (int j = 0; j < nbrofBanks; j++) {
-        bankstate[j] = 0;
+      num_active_banks = 0;
+      for (auto& b : bankstate) {
+        b = 0;
       }
     } else if (type == MemCommand::PRE) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is explicit PRE - update number of precharges, bank
       // state of the target bank and last and latest precharge cycle.
       // Calculate the number of active cycles if the memory was in the
       // active state before, but there is a state transition to PRE now.
       // If not, update the number of precharged cycles and idle cycles.
       // Update memory state if needed.
-      if (bankstate[bank] == 1) {
+      if (bankstate[static_cast<size_t>(bank)] == 1) {
         numberofpres++;
       }
-      bankstate[bank] = 0;
+      bankstate[static_cast<size_t>(bank)] = 0;
 
-      if (mem_state == 1) {
+      if (num_active_banks == 1) {
         actcycles     += max(zero, timestamp - first_act_cycle);
         last_pre_cycle = timestamp;
         idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
                         latest_act_cycle, timestamp);
-      } else if (mem_state == 0) {
+      } else if (num_active_banks == 0) {
         precycles     += max(zero, timestamp - last_pre_cycle);
         idle_pre_update(memSpec, timestamp, latest_pre_cycle);
         last_pre_cycle = timestamp;
       }
       latest_pre_cycle = timestamp;
-      if (mem_state > 0) {
-        mem_state--;
+      if (num_active_banks > 0) {
+        num_active_banks--;
       } else {
-        mem_state = 0;
+        num_active_banks = 0;
       }
     } else if (type == MemCommand::PREA) {
+      printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
       // If command is explicit PREA (precharge all banks) - update
       // number of precharges by the number of banks, update the bank
       // state of all banks to PRE and set the precharge cycle.
       // Calculate the number of active cycles if the memory was in the
       // active state before, but there is a state transition to PRE now.
       // If not, update the number of precharged cycles and idle cycles.
-      if (timestamp == 0) {
-        numberofpres += 0;
-      } else {
-        numberofpres += mem_state;
-      }
+        numberofpres += num_active_banks;
 
-      if (mem_state > 0) {
+      if (num_active_banks > 0) {
         actcycles += max(zero, timestamp - first_act_cycle);
         idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
                         latest_act_cycle, timestamp);
-      } else if (mem_state == 0) {
+      } else if (num_active_banks == 0) {
         precycles += max(zero, timestamp - last_pre_cycle);
         idle_pre_update(memSpec, timestamp, latest_pre_cycle);
       }
@@ -378,10 +321,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
       latest_pre_cycle = timestamp;
       last_pre_cycle   = timestamp;
 
-      mem_state        = 0;
+      num_active_banks        = 0;
 
-      for (int j = 0; j < nbrofBanks; j++) {
-        bankstate[j] = 0;
+      for (auto& b : bankstate) {
+        b = 0;
       }
     } else if (type == MemCommand::PDN_F_ACT) {
       // If command is fast-exit active power-down - update number of
@@ -391,9 +334,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
       // after powering-up. Update active and active idle cycles.
       printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
       f_act_pdns++;
-      for (int j = 0; j < nbrofBanks; j++) {
-        last_states[j] = bankstate[j];
-      }
+      last_states = bankstate;
       pdn_cycle  = timestamp;
       actcycles += max(zero, timestamp - first_act_cycle);
       idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
@@ -407,9 +348,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
       // after powering-up. Update active and active idle cycles.
       printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
       s_act_pdns++;
-      for (int j = 0; j < nbrofBanks; j++) {
-        last_states[j] = bankstate[j];
-      }
+      last_states = bankstate;
       pdn_cycle  = timestamp;
       actcycles += max(zero, timestamp - first_act_cycle);
       idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
@@ -461,14 +400,14 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
                                  memSpec.memTimingSpec.XPDLL -
                                  (2 * memSpec.memTimingSpec.RCD));
         }
-      } else if ((mem_state != CommandAnalysis::MS_PDN_S_ACT) || (mem_state !=
-                                                                  CommandAnalysis::MS_PDN_F_ACT)) {
+      } else if (mem_state != CommandAnalysis::MS_PDN_S_ACT || mem_state != CommandAnalysis::MS_PDN_F_ACT) {
         cerr << "Incorrect use of Active Power-Up!" << endl;
       }
+      num_active_banks = 0;
       mem_state = 0;
-      for (int j = 0; j < nbrofBanks; j++) {
-        bankstate[j] = last_states[j];
-        mem_state   += last_states[j];
+      bankstate = last_states;
+      for (auto& a : last_states) {
+        num_active_banks += static_cast<unsigned int>(a);
       }
       first_act_cycle = timestamp;
     } else if (type == MemCommand::PUP_PRE) {
@@ -493,11 +432,11 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
                                  memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
                                  memSpec.memTimingSpec.RP);
         }
-      } else if ((mem_state != CommandAnalysis::MS_PDN_S_PRE) || (mem_state !=
-                                                                  CommandAnalysis::MS_PDN_F_PRE)) {
+      } else if (mem_state != CommandAnalysis::MS_PDN_S_PRE || mem_state != CommandAnalysis::MS_PDN_F_PRE) {
         cerr << "Incorrect use of Precharged Power-Up!" << endl;
       }
       mem_state      = 0;
+      num_active_banks = 0;
       last_pre_cycle = timestamp;
     } else if (type == MemCommand::SREN) {
       // If command is self-refresh - update number of self-refreshes,
@@ -583,14 +522,15 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
         }
       }
       mem_state = 0;
-    } else if ((type == MemCommand::END) || (type == MemCommand::NOP)) {
+      num_active_banks = 0;
+    } else if (type == MemCommand::END || type == MemCommand::NOP) {
       // May be optionally used at the end of memory trace for better accuracy
       // Update all counters based on completion of operations.
-      if ((mem_state > 0) && (mem_state < 9)) {
+      if (num_active_banks > 0 && mem_state == 0) {
         actcycles += max(zero, timestamp - first_act_cycle);
         idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
                         latest_act_cycle, timestamp);
-      } else if (mem_state == 0) {
+      } else if (num_active_banks == 0 && mem_state == 0) {
         precycles += max(zero, timestamp - last_pre_cycle);
         idle_pre_update(memSpec, timestamp, latest_pre_cycle);
       } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
@@ -604,6 +544,9 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
       } else if (mem_state == CommandAnalysis::MS_SREF) {
         sref_cycles += max(zero, timestamp - sref_cycle);
       }
+    } else {
+      printWarning("Unknown command given, exiting.", type, timestamp, bank);
+      exit(-1);
     }
   }
 } // CommandAnalysis::evaluate
@@ -646,14 +589,21 @@ void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
 
 void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
 {
-  if (mem_state != 0) {
+  if (num_active_banks != 0) {
     printWarning(warning, type, timestamp, bank);
   }
 }
 
 void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
 {
-  if (mem_state == 0) {
+  if (num_active_banks == 0) {
+    printWarning(warning, type, timestamp, bank);
+  }
+}
+
+void CommandAnalysis::printWarningIfPoweredDown(const string& warning, int type, int64_t timestamp, int bank)
+{
+  if (mem_state != 0) {
     printWarning(warning, type, timestamp, bank);
   }
 }
index b5c7ac77864cb6e21e173de023616336be29e097..15261fb2ffd3ed19db1fd0d29b1c2a4317dc9a87 100644 (file)
@@ -58,10 +58,8 @@ class CommandAnalysis {
     MS_PDN_S_PRE = 13, MS_SREF = 14
   };
 
-  CommandAnalysis();
-
   // Returns number of reads, writes, acts, pres and refs in the trace
-  CommandAnalysis(const int nbrofBanks);
+  CommandAnalysis(const int64_t nbrofBanks);
 
   // Number of activate commands
   int64_t numberofacts;
@@ -117,29 +115,25 @@ class CommandAnalysis {
   // Number of precharged auto-refresh cycles during self-refresh exit
   int64_t spup_ref_pre_cycles;
 
+  // function for clearing counters
+  void clearStats(const int64_t timestamp);
+
   // function for clearing arrays
   void clear();
 
   // To identify auto-precharges
   void getCommands(const MemorySpecification& memSpec,
-                   const int
-                   nbrofBanks,
                    std::vector<MemCommand>&   list,
                    bool                       lastupdate);
 
  private:
-  unsigned init;
   int64_t  zero;
-  unsigned pop;
   // Cached last read command from the file
   std::vector<MemCommand> cached_cmd;
 
   // Stores the memory commands for analysis
   std::vector<MemCommand> cmd_list;
 
-  // Stores all memory commands for analysis
-  std::vector<MemCommand> full_cmd_list;
-
   // To save states of the different banks, before entering active
   // power-down mode (slow/fast-exit).
   std::vector<int> last_states;
@@ -171,26 +165,20 @@ class CommandAnalysis {
 
   // Memory State
   unsigned mem_state;
+  unsigned num_active_banks;
 
   // Clock cycle of first activate command when memory state changes to ACT
   int64_t first_act_cycle;
 
   // Clock cycle of last precharge command when memory state changes to PRE
   int64_t last_pre_cycle;
-  // To collect and analyse all commands including auto-precharges
-  void analyse_commands(const int nbrofBanks,
-                        Data::MemorySpecification
-                        memSpec,
-                        int64_t    nCommands,
-                        int64_t    nCached,
-                        bool      lastupdate);
+
   // To perform timing analysis of a given set of commands and update command counters
   void evaluate(const MemorySpecification& memSpec,
-                std::vector<MemCommand>&   cmd_list,
-                int                        nbrofBanks);
+                std::vector<MemCommand>&   cmd_list);
 
   // To calculate time of completion of any issued command
-  int timeToCompletion(const MemorySpecification& memSpec,
+  int64_t timeToCompletion(const MemorySpecification& memSpec,
                        MemCommand::cmds           type);
 
   // To update idle period information whenever active cycles may be idle
@@ -207,6 +195,7 @@ class CommandAnalysis {
 
   void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, int bank);
   void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, int bank);
+  void printWarningIfPoweredDown(const std::string& warning, int type, int64_t timestamp, int bank);
   void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
 };
 }
index ca79edc912886d6f3b32b611b083a20603f96320..49eddc8ac183411e67289e966375bdb997fced9a 100644 (file)
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Karthik Chandrasekar
+ * Authors: Karthik Chandrasekar, Sven Goossens
  *
  */
 
 #ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H
 #define TOOLS_MEM_ARCHITECTURE_SPEC_H
 
+#include <stdint.h>
+
 #include "Parametrisable.h"
 
 namespace Data {
@@ -46,14 +48,14 @@ class MemArchitectureSpec : public virtual Parametrisable {
   MemArchitectureSpec();
   void processParameters();
 
-  unsigned int burstLength;
-  unsigned nbrOfBanks;
-  unsigned nbrOfRanks;
-  unsigned dataRate;
-  unsigned nbrOfColumns;
-  unsigned nbrOfRows;
-  unsigned width;
-  unsigned nbrOfBankGroups;
+  int64_t burstLength;
+  int64_t nbrOfBanks;
+  int64_t nbrOfRanks;
+  int64_t dataRate;
+  int64_t nbrOfColumns;
+  int64_t nbrOfRows;
+  int64_t width;
+  int64_t nbrOfBankGroups;
   bool dll;
   bool twoVoltageDomains;
   bool termination;
index 156716c2f6ea0c715e1e08800563c78ae38487e7..5e1115e0508ce9d904481c42a63bb50fe9481993 100644 (file)
 using namespace Data;
 using namespace std;
 
-MemCommand::MemCommand() :
-  type(MemCommand::PRE),
-  bank(0),
-  timestamp(0)
-{
-}
 
 MemCommand::MemCommand(MemCommand::cmds type,
-                       unsigned bank, double timestamp) :
+                       unsigned bank, int64_t timestamp) :
   type(type),
   bank(bank),
   timestamp(timestamp)
@@ -80,35 +74,35 @@ unsigned MemCommand::getBank() const
 }
 
 // For auto-precharge with read or write - to calculate cycle of precharge
-int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
+int64_t MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
                                    MemCommand::cmds           type) const
 {
-  int precharge_offset = 0;
+  int64_t precharge_offset = 0;
 
-  int BL(static_cast<int>(memSpec.memArchSpec.burstLength));
-  int RTP(static_cast<int>(memSpec.memTimingSpec.RTP));
-  int dataRate(static_cast<int>(memSpec.memArchSpec.dataRate));
-  int AL(static_cast<int>(memSpec.memTimingSpec.AL));
-  int WL(static_cast<int>(memSpec.memTimingSpec.WL));
-  int WR(static_cast<int>(memSpec.memTimingSpec.WR));
-  int B = BL/dataRate;
+  int64_t BL = memSpec.memArchSpec.burstLength;
+  int64_t RTP = memSpec.memTimingSpec.RTP;
+  int64_t dataRate = memSpec.memArchSpec.dataRate;
+  int64_t AL = memSpec.memTimingSpec.AL;
+  int64_t WL = memSpec.memTimingSpec.WL;
+  int64_t WR = memSpec.memTimingSpec.WR;
+  int64_t B = BL/dataRate;
 
   const MemoryType::MemoryType_t& memType = memSpec.memoryType;
 
   // Read with auto-precharge
   if (type == MemCommand::RDA) {
     if (memType == MemoryType::DDR2) {
-      precharge_offset = B + AL - 2 + max(RTP, 2);
+      precharge_offset = B + AL - 2 + max(RTP, int64_t(2));
     } else if (memType == MemoryType::DDR3) {
-      precharge_offset = AL + max(RTP, 4);
+      precharge_offset = AL + max(RTP, int64_t(4));
     } else if (memType == MemoryType::DDR4) {
       precharge_offset = AL + RTP;
     } else if (memType == MemoryType::LPDDR) {
       precharge_offset = B;
     } else if (memType == MemoryType::LPDDR2) {
-      precharge_offset = B + max(0, RTP - 2);
+      precharge_offset = B + max(int64_t(0), RTP - 2);
     } else if (memType == MemoryType::LPDDR3) {
-      precharge_offset = B + max(0, RTP - 4);
+      precharge_offset = B + max(int64_t(0), RTP - 4);
     } else if (memType == MemoryType::WIDEIO_SDR) {
       precharge_offset = B;
     }
@@ -133,19 +127,14 @@ int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
   return precharge_offset;
 } // MemCommand::getPrechargeOffset
 
-void MemCommand::setTime(double _timestamp)
+void MemCommand::setTime(int64_t _timestamp)
 {
   timestamp = _timestamp;
 }
 
-double MemCommand::getTime() const
-{
-  return timestamp;
-}
-
 int64_t MemCommand::getTimeInt64() const
 {
-  return static_cast<int64_t>(timestamp);
+  return timestamp;
 }
 
 MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const
index ea7164577dca2b982e100d4567903e48ed026e7f..9eb75108869f0074daa67499fff8693bd0dea90c 100644 (file)
@@ -86,17 +86,18 @@ class MemCommand {
     PUP_ACT   = 14,
     SREN      = 15,
     SREX      = 16,
-    NOP       = 17
+    NOP       = 17,
+    UNINITIALIZED = 18
   };
 
-  MemCommand();
+//  MemCommand();
   MemCommand(
     // Command Type
-    MemCommand::cmds type,
+    MemCommand::cmds type = UNINITIALIZED,
     // Target Bank
     unsigned         bank = 0,
     // Command Issue Timestamp (in cc)
-    double           timestamp = 0);
+    int64_t          timestamp = 0L);
 
   // Get command type
   cmds getType() const;
@@ -111,16 +112,15 @@ class MemCommand {
   unsigned getBank() const;
 
   // Set timestamp
-  void setTime(double _timestamp);
+  void setTime(int64_t _timestamp);
 
   // Get timestamp
-  double getTime() const;
   int64_t getTimeInt64() const;
 
   cmds typeWithoutAutoPrechargeFlag() const;
 
   // To calculate precharge offset after read or write with auto-precharge
-  int getPrechargeOffset(const MemorySpecification& memSpec,
+  int64_t getPrechargeOffset(const MemorySpecification& memSpec,
                          MemCommand::cmds           type) const;
 
   // To check for equivalence
@@ -136,19 +136,35 @@ class MemCommand {
     }
   }
 
-  static const unsigned int nCommands = 18;
+  static const unsigned int nCommands = 19;
 
   static std::string* getCommandTypeStrings()
   {
-    static std::string type_map[nCommands] = { "ACT",       "RD",      "WR",      "PRE",  "REF",
-                                               "END",       "RDA",     "WRA",     "PREA", "PDN_F_PRE","PDN_S_PRE",  "PDN_F_ACT",
-                                               "PDN_S_ACT", "PUP_PRE", "PUP_ACT", "SREN", "SREX",     "NOP" };
+    static std::string type_map[nCommands] = { "ACT",
+                                               "RD",
+                                               "WR",
+                                               "PRE",
+                                               "REF",
+                                               "END",
+                                               "RDA",
+                                               "WRA",
+                                               "PREA",
+                                               "PDN_F_PRE",
+                                               "PDN_S_PRE",
+                                               "PDN_F_ACT",
+                                               "PDN_S_ACT",
+                                               "PUP_PRE",
+                                               "PUP_ACT",
+                                               "SREN",
+                                               "SREX",
+                                               "NOP",
+                                               "UNINITIALIZED" };
 
     return type_map;
   }
 
   // To identify command type from name
-  static cmds getTypeFromName(const std::string name)
+  static cmds getTypeFromName(const std::string& name)
   {
     std::string* typeStrings = getCommandTypeStrings();
 
@@ -165,7 +181,7 @@ class MemCommand {
  private:
   MemCommand::cmds type;
   unsigned bank;
-  double timestamp;
+  int64_t timestamp;
 };
 }
 #endif // ifndef MEMCOMMAND_H
index 1c3a80c6efa2a426f82fe16a1c2d1416d0fad824..104bf5c71980876aa7f21ca9dc97995a75977059 100644 (file)
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
- * Authors: Karthik Chandrasekar
+ * Authors: Karthik Chandrasekar, Sven Goossens
  *
  */
 
+#include <stdint.h>
+
 #include "Parametrisable.h"
 
 namespace Data {
@@ -44,35 +46,35 @@ class MemTimingSpec : public virtual Parametrisable {
   void processParameters();
 
   double clkMhz;
-  unsigned RC;
-  unsigned RCD;
-  unsigned CCD;
-  unsigned CCD_S;
-  unsigned CCD_L;
-  unsigned RRD;
-  unsigned RRD_S;
-  unsigned RRD_L;
-  unsigned FAW;
-  unsigned TAW;
-  unsigned WTR;
-  unsigned WTR_S;
-  unsigned WTR_L;
-  unsigned REFI;
-  unsigned RL;
-  unsigned RP;
-  unsigned RFC;
-  unsigned RAS;
-  unsigned WL;
-  unsigned AL;
-  unsigned DQSCK;
-  unsigned RTP;
-  unsigned WR;
-  unsigned XP;
-  unsigned XPDLL;
-  unsigned XS;
-  unsigned XSDLL;
-  unsigned CKE;
-  unsigned CKESR;
+  int64_t RC;
+  int64_t RCD;
+  int64_t CCD;
+  int64_t CCD_S;
+  int64_t CCD_L;
+  int64_t RRD;
+  int64_t RRD_S;
+  int64_t RRD_L;
+  int64_t FAW;
+  int64_t TAW;
+  int64_t WTR;
+  int64_t WTR_S;
+  int64_t WTR_L;
+  int64_t REFI;
+  int64_t RL;
+  int64_t RP;
+  int64_t RFC;
+  int64_t RAS;
+  int64_t WL;
+  int64_t AL;
+  int64_t DQSCK;
+  int64_t RTP;
+  int64_t WR;
+  int64_t XP;
+  int64_t XPDLL;
+  int64_t XS;
+  int64_t XSDLL;
+  int64_t CKE;
+  int64_t CKESR;
   double   clkPeriod;
 };
 }
index 4817d1bb516c9818fce8a8989b891e82bed592ba..e020830e67452b8a458b3d9bc293a8155d8e8c39 100644 (file)
 
 #include "MemoryPowerModel.h"
 
-#include <cmath>  // For pow
-
 #include <stdint.h>
 
+#include <cmath>  // For pow
+#include <iostream>  // fmtflags
+
 
 using namespace std;
 using namespace Data;
 
 // Calculate energy and average power consumption for the given command trace
 
-void MemoryPowerModel::power_calc(MemorySpecification memSpec,
-                                  const CommandAnalysis& counters,
+void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
+                                  const CommandAnalysis& c,
                                   int term)
 {
-  MemTimingSpec& t                 = memSpec.memTimingSpec;
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
-  MemPowerSpec&  mps               = memSpec.memPowerSpec;
+  const MemTimingSpec& t                 = memSpec.memTimingSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const MemPowerSpec&  mps               = memSpec.memPowerSpec;
 
   energy.act_energy          = 0.0;
   energy.pre_energy          = 0.0;
@@ -102,16 +103,16 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
     // 1 DQS and 1 DM pin is associated with every data byte
     int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8;
     // Size of one clock period for the data bus.
-    double ddrPeriod = t.clkPeriod / memArchSpec.dataRate;
+    double ddrPeriod = t.clkPeriod / static_cast<double>(memArchSpec.dataRate);
 
     // Read IO power is consumed by each DQ (data) and DQS (data strobe) pin
-    energy.read_io_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
+    energy.read_io_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
                                              ddrPeriod,
                                              power.IO_power,
                                              dqPlusDqsBits);
 
     // Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM
-    energy.write_term_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
+    energy.write_term_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
                                                 ddrPeriod,
                                                 power.WR_ODT_power,
                                                 dqPlusDqsPlusMaskBits);
@@ -119,14 +120,14 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
     if (memArchSpec.nbrOfRanks > 1) {
       // Termination power consumed in the idle rank during reads on the active
       // rank by each DQ (data) and DQS (data strobe) pin.
-      energy.read_oterm_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
+      energy.read_oterm_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
                                                   ddrPeriod,
                                                   power.TermRD_power,
                                                   dqPlusDqsBits);
 
       // Termination power consumed in the idle rank during writes on the active
       // rank by each DQ (data), DQS (data strobe) and DM (data mask) pin.
-      energy.write_oterm_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
+      energy.write_oterm_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
                                                    ddrPeriod,
                                                    power.TermWR_power,
                                                    dqPlusDqsPlusMaskBits);
@@ -137,101 +138,101 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
                             + energy.read_oterm_energy + energy.write_oterm_energy;
   }
 
-  total_cycles = counters.actcycles + counters.precycles +
-                 counters.f_act_pdcycles + counters.f_pre_pdcycles +
-                 counters.s_act_pdcycles + counters.s_pre_pdcycles + counters.sref_cycles
-                 + counters.sref_ref_act_cycles + counters.sref_ref_pre_cycles +
-                 counters.spup_ref_act_cycles + counters.spup_ref_pre_cycles;
+  total_cycles = c.actcycles + c.precycles +
+                 c.f_act_pdcycles + c.f_pre_pdcycles +
+                 c.s_act_pdcycles + c.s_pre_pdcycles + c.sref_cycles
+                 + c.sref_ref_act_cycles + c.sref_ref_pre_cycles +
+                 c.spup_ref_act_cycles + c.spup_ref_pre_cycles;
 
   EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
 
-  energy.act_energy       = vdd0Domain.calcTivEnergy(counters.numberofacts   * t.RAS          , mps.idd0 - mps.idd3n);
-  energy.pre_energy       = vdd0Domain.calcTivEnergy(counters.numberofpres   * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
-  energy.read_energy      = vdd0Domain.calcTivEnergy(counters.numberofreads  * burstCc        , mps.idd4r - mps.idd3n);
-  energy.write_energy     = vdd0Domain.calcTivEnergy(counters.numberofwrites * burstCc        , mps.idd4w - mps.idd3n);
-  energy.ref_energy       = vdd0Domain.calcTivEnergy(counters.numberofrefs   * t.RFC          , mps.idd5 - mps.idd3n);
-  energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(counters.precycles, mps.idd2n);
-  energy.act_stdby_energy = vdd0Domain.calcTivEnergy(counters.actcycles, mps.idd3n);
+  energy.act_energy       = vdd0Domain.calcTivEnergy(c.numberofacts   * t.RAS          , mps.idd0 - mps.idd3n);
+  energy.pre_energy       = vdd0Domain.calcTivEnergy(c.numberofpres   * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
+  energy.read_energy      = vdd0Domain.calcTivEnergy(c.numberofreads  * burstCc        , mps.idd4r - mps.idd3n);
+  energy.write_energy     = vdd0Domain.calcTivEnergy(c.numberofwrites * burstCc        , mps.idd4w - mps.idd3n);
+  energy.ref_energy       = vdd0Domain.calcTivEnergy(c.numberofrefs   * t.RFC          , mps.idd5 - mps.idd3n);
+  energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(c.precycles, mps.idd2n);
+  energy.act_stdby_energy = vdd0Domain.calcTivEnergy(c.actcycles, mps.idd3n);
   // Idle energy in the active standby clock cycles
-  energy.idle_energy_act  = vdd0Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n);
+  energy.idle_energy_act  = vdd0Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n);
   // Idle energy in the precharge standby clock cycles
-  energy.idle_energy_pre  = vdd0Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n);
+  energy.idle_energy_pre  = vdd0Domain.calcTivEnergy(c.idlecycles_pre, mps.idd2n);
   // fast-exit active power-down cycles energy
-  energy.f_act_pd_energy  = vdd0Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p1);
+  energy.f_act_pd_energy  = vdd0Domain.calcTivEnergy(c.f_act_pdcycles, mps.idd3p1);
   // fast-exit precharged power-down cycles energy
-  energy.f_pre_pd_energy  = vdd0Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p1);
+  energy.f_pre_pd_energy  = vdd0Domain.calcTivEnergy(c.f_pre_pdcycles, mps.idd2p1);
   // slow-exit active power-down cycles energy
-  energy.s_act_pd_energy  = vdd0Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p0);
+  energy.s_act_pd_energy  = vdd0Domain.calcTivEnergy(c.s_act_pdcycles, mps.idd3p0);
   // slow-exit precharged power-down cycles energy
-  energy.s_pre_pd_energy  = vdd0Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p0);
+  energy.s_pre_pd_energy  = vdd0Domain.calcTivEnergy(c.s_pre_pdcycles, mps.idd2p0);
 
   // self-refresh cycles energy including a refresh per self-refresh entry
   energy.sref_energy = engy_sref(mps.idd6, mps.idd3n,
                                  mps.idd5, mps.vdd,
-                                 static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
-                                 static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
-                                 static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
+                                 static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
+                                 static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
+                                 static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
 
   // background energy during active auto-refresh cycles in self-refresh
-  energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p0);
+  energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(c.sref_ref_act_cycles, mps.idd3p0);
   // background energy during precharged auto-refresh cycles in self-refresh
-  energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p0);
+  energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(c.sref_ref_pre_cycles, mps.idd2p0);
   // background energy during active auto-refresh cycles in self-refresh exit
-  energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n);
+  energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(c.spup_ref_act_cycles, mps.idd3n);
   // background energy during precharged auto-refresh cycles in self-refresh exit
-  energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n);
+  energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(c.spup_ref_pre_cycles, mps.idd2n);
   // self-refresh power-up cycles energy -- included
-  energy.spup_energy         = vdd0Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n);
+  energy.spup_energy         = vdd0Domain.calcTivEnergy(c.spup_cycles, mps.idd2n);
   // active power-up cycles energy - same as active standby -- included
-  energy.pup_act_energy      = vdd0Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n);
+  energy.pup_act_energy      = vdd0Domain.calcTivEnergy(c.pup_act_cycles, mps.idd3n);
   // precharged power-up cycles energy - same as precharged standby -- included
-  energy.pup_pre_energy      = vdd0Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n);
+  energy.pup_pre_energy      = vdd0Domain.calcTivEnergy(c.pup_pre_cycles, mps.idd2n);
 
   // similar equations as before to support multiple voltage domains in LPDDR2
   // and WIDEIO memories
   if (memArchSpec.twoVoltageDomains) {
     EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
 
-    energy.act_energy       += vdd2Domain.calcTivEnergy(counters.numberofacts   * t.RAS          , mps.idd02 - mps.idd3n2);
-    energy.pre_energy       += vdd2Domain.calcTivEnergy(counters.numberofpres   * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
-    energy.read_energy      += vdd2Domain.calcTivEnergy(counters.numberofreads  * burstCc        , mps.idd4r2 - mps.idd3n2);
-    energy.write_energy     += vdd2Domain.calcTivEnergy(counters.numberofwrites * burstCc        , mps.idd4w2 - mps.idd3n2);
-    energy.ref_energy       += vdd2Domain.calcTivEnergy(counters.numberofrefs   * t.RFC          , mps.idd52 - mps.idd3n2);
-    energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(counters.precycles, mps.idd2n2);
-    energy.act_stdby_energy += vdd2Domain.calcTivEnergy(counters.actcycles, mps.idd3n2);
+    energy.act_energy       += vdd2Domain.calcTivEnergy(c.numberofacts   * t.RAS          , mps.idd02 - mps.idd3n2);
+    energy.pre_energy       += vdd2Domain.calcTivEnergy(c.numberofpres   * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
+    energy.read_energy      += vdd2Domain.calcTivEnergy(c.numberofreads  * burstCc        , mps.idd4r2 - mps.idd3n2);
+    energy.write_energy     += vdd2Domain.calcTivEnergy(c.numberofwrites * burstCc        , mps.idd4w2 - mps.idd3n2);
+    energy.ref_energy       += vdd2Domain.calcTivEnergy(c.numberofrefs   * t.RFC          , mps.idd52 - mps.idd3n2);
+    energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(c.precycles, mps.idd2n2);
+    energy.act_stdby_energy += vdd2Domain.calcTivEnergy(c.actcycles, mps.idd3n2);
     // Idle energy in the active standby clock cycles
-    energy.idle_energy_act  += vdd2Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n2);
+    energy.idle_energy_act  += vdd2Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n2);
     // Idle energy in the precharge standby clock cycles
-    energy.idle_energy_pre  += vdd2Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n2);
+    energy.idle_energy_pre  += vdd2Domain.calcTivEnergy(c.idlecycles_pre, mps.idd2n2);
     // fast-exit active power-down cycles energy
-    energy.f_act_pd_energy  += vdd2Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p12);
+    energy.f_act_pd_energy  += vdd2Domain.calcTivEnergy(c.f_act_pdcycles, mps.idd3p12);
     // fast-exit precharged power-down cycles energy
-    energy.f_pre_pd_energy  += vdd2Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p12);
+    energy.f_pre_pd_energy  += vdd2Domain.calcTivEnergy(c.f_pre_pdcycles, mps.idd2p12);
     // slow-exit active power-down cycles energy
-    energy.s_act_pd_energy  += vdd2Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p02);
+    energy.s_act_pd_energy  += vdd2Domain.calcTivEnergy(c.s_act_pdcycles, mps.idd3p02);
     // slow-exit precharged power-down cycles energy
-    energy.s_pre_pd_energy  += vdd2Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p02);
+    energy.s_pre_pd_energy  += vdd2Domain.calcTivEnergy(c.s_pre_pdcycles, mps.idd2p02);
 
     energy.sref_energy      += engy_sref(mps.idd62, mps.idd3n2,
                                          mps.idd52, mps.vdd2,
-                                         static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
-                                         static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
-                                         static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
+                                         static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
+                                         static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
+                                         static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
 
     // background energy during active auto-refresh cycles in self-refresh
-    energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p02);
+    energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(c.sref_ref_act_cycles, mps.idd3p02);
     // background energy during precharged auto-refresh cycles in self-refresh
-    energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p02);
+    energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(c.sref_ref_pre_cycles, mps.idd2p02);
     // background energy during active auto-refresh cycles in self-refresh exit
-    energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n2);
+    energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(c.spup_ref_act_cycles, mps.idd3n2);
     // background energy during precharged auto-refresh cycles in self-refresh exit
-    energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n2);
+    energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(c.spup_ref_pre_cycles, mps.idd2n2);
     // self-refresh power-up cycles energy -- included
-    energy.spup_energy         += vdd2Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n2);
+    energy.spup_energy         += vdd2Domain.calcTivEnergy(c.spup_cycles, mps.idd2n2);
     // active power-up cycles energy - same as active standby -- included
-    energy.pup_act_energy      += vdd2Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n2);
+    energy.pup_act_energy      += vdd2Domain.calcTivEnergy(c.pup_act_cycles, mps.idd3n2);
     // precharged power-up cycles energy - same as precharged standby -- included
-    energy.pup_pre_energy      += vdd2Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n2);
+    energy.pup_pre_energy      += vdd2Domain.calcTivEnergy(c.pup_pre_cycles, mps.idd2n2);
   }
 
   // auto-refresh energy during self-refresh cycles
@@ -244,7 +245,7 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
   // energy components for both ranks (in a dual-rank system)
   energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
                         energy.write_energy + energy.ref_energy + energy.io_term_energy +
-                        memArchSpec.nbrOfRanks * (energy.act_stdby_energy +
+                        static_cast<double>(memArchSpec.nbrOfRanks) * (energy.act_stdby_energy +
                                                   energy.pre_stdby_energy + energy.sref_energy +
                                                   energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy
                                                   + energy.s_pre_pd_energy + energy.sref_ref_energy + energy.spup_ref_energy);
@@ -253,130 +254,100 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
   power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
 } // MemoryPowerModel::power_calc
 
-void MemoryPowerModel::power_print(MemorySpecification memSpec, int term, const CommandAnalysis& counters) const
+void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term, const CommandAnalysis& c) const
 {
-  MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const uint64_t nRanks = static_cast<uint64_t>(memArchSpec.nbrOfRanks);
+  const char eUnit[] = " pJ";
 
+  ios_base::fmtflags flags = cout.flags();
+  streamsize precision = cout.precision();
   cout.precision(0);
-  cout << "* Trace Details:" << endl;
-  cout << "Number of Activates: " << fixed << counters.numberofacts << endl;
-  cout << "Number of Reads: " << counters.numberofreads << endl;
-  cout << "Number of Writes: " << counters.numberofwrites << endl;
-  cout << "Number of Precharges: " << counters.numberofpres << endl;
-  cout << "Number of Refreshes: " << counters.numberofrefs << endl;
-  cout << "Number of Active Cycles: " << counters.actcycles << endl;
-  cout << "  Number of Active Idle Cycles: " << counters.idlecycles_act << endl;
-  cout << "  Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl;
-  cout << "    Number of Auto-Refresh Active cycles during Self-Refresh " <<
-    "Power-Up: " << counters.spup_ref_act_cycles << endl;
-  cout << "Number of Precharged Cycles: " << counters.precycles << endl;
-  cout << "  Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl;
-  cout << "  Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles
-       << endl;
-  cout << "    Number of Auto-Refresh Precharged cycles during Self-Refresh"
-       << " Power-Up: " << counters.spup_ref_pre_cycles << endl;
-  cout << "  Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles
-       << endl;
-  cout << "Total Idle Cycles (Active + Precharged): " <<
-    counters.idlecycles_act + counters.idlecycles_pre << endl;
-  cout << "Number of Power-Downs: " << counters.f_act_pdns +
-    counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl;
-  cout << "  Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns
-       << endl;
-  cout << "  Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns
-       << endl;
-  cout << "  Number of Precharged Fast-exit Power-Downs: " <<
-    counters.f_pre_pdns << endl;
-  cout << "  Number of Precharged Slow-exit Power-Downs: " <<
-    counters.s_pre_pdns << endl;
-  cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles +
-    counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl;
-  cout << "  Number of Active Fast-exit Power-Down Cycles: " <<
-    counters.f_act_pdcycles << endl;
-  cout << "  Number of Active Slow-exit Power-Down Cycles: " <<
-    counters.s_act_pdcycles << endl;
-  cout << "    Number of Auto-Refresh Active cycles during Self-Refresh: " <<
-    counters.sref_ref_act_cycles << endl;
-  cout << "  Number of Precharged Fast-exit Power-Down Cycles: " <<
-    counters.f_pre_pdcycles << endl;
-  cout << "  Number of Precharged Slow-exit Power-Down Cycles: " <<
-    counters.s_pre_pdcycles << endl;
-  cout << "    Number of Auto-Refresh Precharged cycles during Self-Refresh: " <<
-    counters.sref_ref_pre_cycles << endl;
-  cout << "Number of Auto-Refresh Cycles: " << counters.numberofrefs *
-    memTimingSpec.RFC << endl;
-  cout << "Number of Self-Refreshes: " << counters.numberofsrefs << endl;
-  cout << "Number of Self-Refresh Cycles: " << counters.sref_cycles << endl;
-  cout << "----------------------------------------" << endl;
-  cout << "Total Trace Length (clock cycles): " << total_cycles << endl;
-  cout << "----------------------------------------" << endl;
+  cout << "* Trace Details:" << fixed << endl
+       << endl << "#ACT commands: "                 << c.numberofacts
+       << endl << "#RD + #RDA commands: "           << c.numberofreads
+       << endl << "#WR + #WRA commands: "           << c.numberofwrites
+  /* #PRE commands (precharge all counts a number of #PRE commands equal to the number of active banks) */
+       << endl << "#PRE (+ PREA) commands: "        << c.numberofpres
+       << endl << "#REF commands: "                 << c.numberofrefs
+       << endl << "#Active Cycles: "                << c.actcycles
+       << endl << "  #Active Idle Cycles: "         << c.idlecycles_act
+       << endl << "  #Active Power-Up Cycles: "     << c.pup_act_cycles
+       << endl << "    #Auto-Refresh Active cycles during Self-Refresh Power-Up: " << c.spup_ref_act_cycles
+       << endl << "#Precharged Cycles: "            << c.precycles
+       << endl << "  #Precharged Idle Cycles: "     << c.idlecycles_pre
+       << endl << "  #Precharged Power-Up Cycles: " << c.pup_pre_cycles
+       << endl << "    #Auto-Refresh Precharged cycles during Self-Refresh Power-Up: " << c.spup_ref_pre_cycles
+       << endl << "  #Self-Refresh Power-Up Cycles: "                          << c.spup_cycles
+       << endl << "Total Idle Cycles (Active + Precharged): "                  << c.idlecycles_act + c.idlecycles_pre
+       << endl << "#Power-Downs: "                                             << c.f_act_pdns +  c.s_act_pdns + c.f_pre_pdns + c.s_pre_pdns
+       << endl << "  #Active Fast-exit Power-Downs: "                          << c.f_act_pdns
+       << endl << "  #Active Slow-exit Power-Downs: "                          << c.s_act_pdns
+       << endl << "  #Precharged Fast-exit Power-Downs: "                      << c.f_pre_pdns
+       << endl << "  #Precharged Slow-exit Power-Downs: "                      << c.s_pre_pdns
+       << endl << "#Power-Down Cycles: "                                       << c.f_act_pdcycles + c.s_act_pdcycles + c.f_pre_pdcycles + c.s_pre_pdcycles
+       << endl << "  #Active Fast-exit Power-Down Cycles: "                    << c.f_act_pdcycles
+       << endl << "  #Active Slow-exit Power-Down Cycles: "                    << c.s_act_pdcycles
+       << endl << "    #Auto-Refresh Active cycles during Self-Refresh: "      << c.sref_ref_act_cycles
+       << endl << "  #Precharged Fast-exit Power-Down Cycles: "                << c.f_pre_pdcycles
+       << endl << "  #Precharged Slow-exit Power-Down Cycles: "                << c.s_pre_pdcycles
+       << endl << "    #Auto-Refresh Precharged cycles during Self-Refresh: "  << c.sref_ref_pre_cycles
+       << endl << "#Auto-Refresh Cycles: "                                     << c.numberofrefs * memTimingSpec.RFC
+       << endl << "#Self-Refreshes: "                                          << c.numberofsrefs
+       << endl << "#Self-Refresh Cycles: "                                     << c.sref_cycles
+       << endl << "----------------------------------------"
+       << endl << "Total Trace Length (clock cycles): " << total_cycles
+       << endl << "----------------------------------------" << endl;
+
   cout.precision(2);
+  cout << endl << "* Trace Power and Energy Estimates:" << endl
+       << endl << "ACT Cmd Energy: " << energy.act_energy   << eUnit
+       << endl << "PRE Cmd Energy: " << energy.pre_energy   << eUnit
+       << endl << "RD Cmd Energy: "  << energy.read_energy  << eUnit
+       << endl << "WR Cmd Energy: "  << energy.write_energy << eUnit;
 
-  cout << "\n* Trace Power and Energy Estimates:" << endl;
-  cout << "ACT Cmd Energy: " << energy.act_energy << " pJ" << endl;
-  cout << "PRE Cmd Energy: " << energy.pre_energy << " pJ" << endl;
-  cout << "RD Cmd Energy: " << energy.read_energy << " pJ" << endl;
-  cout << "WR Cmd Energy: " << energy.write_energy << " pJ" << endl;
   if (term) {
-    cout << "RD I/O Energy: " << energy.read_io_energy << " pJ" << endl;
+    cout << "RD I/O Energy: " << energy.read_io_energy << eUnit << endl;
     // No Termination for LPDDR/2/3 and DDR memories
     if (memSpec.memArchSpec.termination) {
-      cout << "WR Termination Energy: " << energy.write_term_energy << " pJ" << endl;
+      cout << "WR Termination Energy: " << energy.write_term_energy << eUnit << endl;
     }
 
-    if ((memArchSpec.nbrOfRanks > 1) && memSpec.memArchSpec.termination) {
-      cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy
-           << " pJ" << endl;
-      cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy
-           << " pJ" << endl;
+    if (nRanks > 1 && memSpec.memArchSpec.termination) {
+      cout <<         "RD Termination Energy (Idle rank): " << energy.read_oterm_energy << eUnit
+           << endl << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy << eUnit << endl;
     }
   }
-  cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy <<
-    " pJ" << endl;
-  cout << "  Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act <<
-    " pJ" << endl;
-  cout << "  Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy <<
-    " pJ" << endl;
-  cout << "    Active Stdby Energy during Auto-Refresh cycles in Self-Refresh"
-       << " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy <<
-    " pJ" << endl;
-  cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy <<
-    " pJ" << endl;
-  cout << "  Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre <<
-    " pJ" << endl;
-  cout << "  Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy <<
-    " pJ" << endl;
-  cout << "    Precharge Stdby Energy during Auto-Refresh cycles " <<
-    "in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy <<
-    " pJ" << endl;
-  cout << "  Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy <<
-    " pJ" << endl;
-  cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks *
-  (energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl;
-  cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy +
-                                                                   energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl;
-  cout << "  Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
-    energy.f_act_pd_energy << " pJ" << endl;
-  cout << "  Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
-    energy.s_act_pd_energy << " pJ" << endl;
-  cout << "    Slow-Exit Active Power-Down Energy during Auto-Refresh cycles "
-       << "in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_act_energy <<
-    " pJ" << endl;
-  cout << "  Fast-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
-    energy.f_pre_pd_energy << " pJ" << endl;
-  cout << "  Slow-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
-    energy.s_pre_pd_energy << " pJ" << endl;
-  cout << "    Slow-Exit Precharged Power-Down Energy during Auto-Refresh " <<
-    "cycles in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_pre_energy <<
-    " pJ" << endl;
-  cout << "Auto-Refresh Energy: " << energy.ref_energy << " pJ" << endl;
-  cout << "Self-Refresh Energy: " << memArchSpec.nbrOfRanks * energy.sref_energy <<
-    " pJ" << endl;
-  cout << "----------------------------------------" << endl;
-  cout << "Total Trace Energy: " << energy.total_energy << " pJ" << endl;
-  cout << "Average Power: " << power.average_power << " mW" << endl;
-  cout << "----------------------------------------" << endl;
+
+  double nRanksDouble = static_cast<double>(nRanks);
+
+  cout <<         "ACT Stdby Energy: "                                                                      << nRanksDouble * energy.act_stdby_energy << eUnit
+       << endl << "  Active Idle Energy: "                                                                  << nRanksDouble * energy.idle_energy_act << eUnit
+       << endl << "  Active Power-Up Energy: "                                                              << nRanksDouble * energy.pup_act_energy << eUnit
+       << endl << "    Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: "           << nRanksDouble * energy.spup_ref_act_energy << eUnit
+       << endl << "PRE Stdby Energy: "                                                                      << nRanksDouble * energy.pre_stdby_energy << eUnit
+       << endl << "  Precharge Idle Energy: "                                                               << nRanksDouble * energy.idle_energy_pre << eUnit
+       << endl << "  Precharged Power-Up Energy: "                                                          << nRanksDouble * energy.pup_pre_energy << eUnit
+       << endl << "    Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: "        << nRanksDouble * energy.spup_ref_pre_energy << eUnit
+       << endl << "  Self-Refresh Power-Up Energy: "                                                        << nRanksDouble * energy.spup_energy << eUnit
+       << endl << "Total Idle Energy (Active + Precharged): "                                               << nRanksDouble * (energy.idle_energy_act + energy.idle_energy_pre) << eUnit
+       << endl << "Total Power-Down Energy: "                                                               << nRanksDouble * (energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << eUnit
+       << endl << "  Fast-Exit Active Power-Down Energy: "                                                  << nRanksDouble * energy.f_act_pd_energy << eUnit
+       << endl << "  Slow-Exit Active Power-Down Energy: "                                                  << nRanksDouble * energy.s_act_pd_energy << eUnit
+       << endl << "    Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: "     << nRanksDouble * energy.sref_ref_act_energy << eUnit
+       << endl << "  Fast-Exit Precharged Power-Down Energy: "                                              << nRanksDouble * energy.f_pre_pd_energy << eUnit
+       << endl << "  Slow-Exit Precharged Power-Down Energy: "                                              << nRanksDouble * energy.s_pre_pd_energy << eUnit
+       << endl << "    Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy << eUnit
+       << endl << "Auto-Refresh Energy: "                                                                   << energy.ref_energy << eUnit
+       << endl << "Self-Refresh Energy: "                                                                   << nRanksDouble * energy.sref_energy << eUnit
+       << endl << "----------------------------------------"
+       << endl << "Total Trace Energy: "                                                                    << energy.total_energy << eUnit
+       << endl << "Average Power: "                                                                         << power.average_power << " mW"
+       << endl << "----------------------------------------" << endl;
+
+  cout.flags(flags);
+  cout.precision(precision);
 } // MemoryPowerModel::power_print
 
 // Self-refresh active energy estimation (not including background energy)
@@ -395,11 +366,11 @@ double MemoryPowerModel::engy_sref(double idd6, double idd3n, double idd5,
 
 // IO and Termination power calculation based on Micron Power Calculators
 // Absolute power measures are obtained from Micron Power Calculator (mentioned in mW)
-void MemoryPowerModel::io_term_power(MemorySpecification memSpec)
+void MemoryPowerModel::io_term_power(const MemorySpecification& memSpec)
 {
-  MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
-  MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
-  MemPowerSpec&  memPowerSpec      = memSpec.memPowerSpec;
+  const MemTimingSpec& memTimingSpec     = memSpec.memTimingSpec;
+  const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+  const MemPowerSpec&  memPowerSpec      = memSpec.memPowerSpec;
 
   power.IO_power     = memPowerSpec.ioPower;    // in mW
   power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW
index b894f67ddba2a460278ee8e0b11206ce3e9fdba2..2b2304989e457ba23367eb902bd02009ecb07fa7 100644 (file)
@@ -46,9 +46,9 @@ class MemoryPowerModel {
  public:
   // Calculate energy and average power consumption for the given memory
   // command trace
-  void power_calc(MemorySpecification    memSpec,
-                  const CommandAnalysis& counters,
-                  int                    term);
+  void power_calc(const MemorySpecification& memSpec,
+                  const CommandAnalysis& c,
+                  int term);
 
   // Used to calculate self-refresh active energy
   static double engy_sref(double idd6,
@@ -145,12 +145,12 @@ class MemoryPowerModel {
   };
 
   // Print the power and energy
-  void power_print(MemorySpecification memSpec,
+  void power_print(const MemorySpecification& memSpec,
                    int                 term,
-                   const CommandAnalysis& counters) const;
+                   const CommandAnalysis& c) const;
 
   // To derive IO and Termination Power measures using DRAM specification
-  void io_term_power(MemorySpecification memSpec);
+  void io_term_power(const MemorySpecification& memSpec);
 
   Energy energy;
   Power  power;
index 149d41c288382abb60516124a7c3d5cbf22f1bdd..16d77ef8683a82e9957fa744e84dd6e1eabbab38 100644 (file)
@@ -106,7 +106,8 @@ class MemoryType {
     return val == LPDDR ||
            val == LPDDR2 ||
            val == LPDDR3 ||
-           val == WIDEIO_SDR;
+           val == WIDEIO_SDR ||
+           val == DDR4;
   }
 
   bool isDDRFamily() const
@@ -132,9 +133,11 @@ class MemoryType {
 
   double getCapacitance() const
   {
-    // LPDDR/2/3 and DDR memories only have IO Power (no ODT)
-    // Conservative estimates based on Micron Mobile LPDDR2 Power Calculator
-      // LPDDR/2/3 IO Capacitance in mF
+    // LPDDR1/2 memories only have IO Power (no ODT)
+    // LPDDR3 has optional ODT, but it is typically not used (reflections are elimitated by other means (layout))
+    // The capacitance values are conservative and based on Micron Mobile LPDDR2 Power Calculator
+
+    // LPDDR/2/3 IO Capacitance in mF
     if (val == LPDDR) {
         return 0.0000000045;
     } else if (val == LPDDR2) {
index ec87f06dac03ed1f9ee743b1cc29a0b18d8ba90e..2cf9a8572c81b305912261b335753e17dea5c5fa 100644 (file)
 using namespace Data;
 using namespace std;
 
+TraceParser::TraceParser(int64_t nbrOfBanks) :
+  counters(nbrOfBanks)
+{
+}
+
+
 Data::MemCommand TraceParser::parseLine(std::string line)
 {
-  MemCommand memcmd;
+  MemCommand memcmd(MemCommand::UNINITIALIZED, 0, 0);
   istringstream linestream(line);
   string item;
-  double item_val;
+  int64_t item_val;
   unsigned itemnum = 0;
-  MemCommand::cmds type = MemCommand::NOP; // Initialized to prevent warning
 
   while (getline(linestream, item, ',')) {
     if (itemnum == 0) {
@@ -62,10 +67,8 @@ Data::MemCommand TraceParser::parseLine(std::string line)
     } else if (itemnum == 2) {
       stringstream bank(item);
       bank >> item_val;
-      memcmd.setType(type);
       memcmd.setBank(static_cast<unsigned>(item_val));
     }
-    type = memcmd.getType();
     itemnum++;
   }
   return memcmd;
@@ -90,13 +93,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
       cmd_list.push_back(cmdline);
       nCommands++;
       if (nCommands == window) {
-        counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
+        counters.getCommands(memSpec, cmd_list, lastupdate);
         nCommands = 0;
         cmd_list.clear();
       }
     }
     lastupdate = true;
-    counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
+    counters.getCommands(memSpec, cmd_list, lastupdate);
     cmd_list.clear();
     pwr_trace.close();
   } else   {
@@ -106,13 +109,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
       cmd_list.push_back(cmdline);
       nCommands++;
       if (nCommands == window) {
-        counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
+        counters.getCommands(memSpec, cmd_list, lastupdate);
         nCommands = 0;
         cmd_list.clear();
       }
     }
     lastupdate = true;
-    counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
+    counters.getCommands(memSpec, cmd_list, lastupdate);
     cmd_list.clear();
   }
   counters.clear();
index cabfcd395d743df806d407856fed8c73d029852c..9727b4800dba94da62023886b2c4e43d374a67eb 100644 (file)
@@ -48,6 +48,7 @@
 
 class TraceParser {
  public:
+  TraceParser(int64_t nbrOfBanks);
   // list of parsed commands
   std::vector<Data::MemCommand> cmd_list;
 
index 4aa8bb22064869e3a1a7572afd2f50d1e1a57573..80f4390c7f6186f789f6845d2ee01f5f1cd37531 100644 (file)
@@ -41,9 +41,7 @@
 #include <string>
 #include <sstream>
 #include <stdexcept>
-#include <typeinfo>
 
-#define MILLION 1000000
 
 template<typename T>
 T fromString(const std::string& s,
@@ -54,7 +52,7 @@ throw(std::runtime_error)
   T t;
 
   if (!(is >> f >> t)) {
-    throw std::runtime_error("fromString cannot convert " + s);
+    throw std::runtime_error("Cannot convert string");
   }
 
   return t;
index ac16f948b21832490916cc7e99127ea4146df018..47ed15a995bde9b2fb49e66bd66059efa2e5403d 100644 (file)
@@ -52,13 +52,13 @@ libDRAMPower::~libDRAMPower()
 
 void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp)
 {
-  MemCommand cmd(type, static_cast<unsigned>(bank), static_cast<double>(timestamp));
+  MemCommand cmd(type, static_cast<unsigned>(bank), timestamp);
   cmdList.push_back(cmd);
 }
 
 void libDRAMPower::updateCounters(bool lastUpdate)
 {
-  counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmdList, lastUpdate);
+  counters.getCommands(memSpec, cmdList, lastUpdate);
   cmdList.clear();
 }
 
@@ -72,6 +72,11 @@ void libDRAMPower::clearState()
   counters.clear();
 }
 
+void libDRAMPower::clearCounters(int64_t timestamp)
+{
+  counters.clearStats(timestamp);
+}
+
 const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
 {
   return mpm.energy;
index 9dea8b0f5190a4e78d513acf434b1bc648989050..4d9ccefe58625795da8c29b6d89afa07c6c389ec 100644 (file)
@@ -56,6 +56,8 @@ class libDRAMPower {
 
   void updateCounters(bool lastUpdate);
 
+  void clearCounters(int64_t timestamp);
+
   void clearState();
 
   void calcEnergy();
index f382a727e33a9b121fc5c32b2cfc965cd0b6a746..20d4d9ebf555edf70846437eb21bfcbfe14650df 100644 (file)
@@ -79,7 +79,8 @@ int main(int argc, char* argv[])
         test.doCommand(MemCommand::RDA,0,210);
         test.doCommand(MemCommand::ACT,4,232);
         test.doCommand(MemCommand::WRA,4,247);
-        test.doCommand(MemCommand::PDN_F_ACT,3,248);
+        // Need at least tWRAPDEN = AL + CWL + BL/2 + WR + 1 cycles between WR and PDN_F_PRE
+        test.doCommand(MemCommand::PDN_F_PRE,3,265);
 
         //set bool to true when this is the last update of the counters
         test.updateCounters(true);
@@ -106,7 +107,7 @@ int main(int argc, char* argv[])
         //test.getEnergy().act_stdby_energy
         std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
         //total active standby energy for both ranks
-        std::cout << "ACT Std Energy total ranks" << "\t" << memSpec.memArchSpec.nbrOfRanks *
+        std::cout << "ACT Std Energy total ranks" << "\t" << static_cast<double>(memSpec.memArchSpec.nbrOfRanks) *
         test.getEnergy().act_stdby_energy << "\n" ;
         std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
         std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;
index 6cd72b266a76f415e0fc30574d7efb4b23024882..f59528492e9dd0e70b20bdc147effccc168edaea 100644 (file)
@@ -41,6 +41,7 @@
  *          Ani Udipi
  *          Neha Agarwal
  *          Omar Naji
+ *          Matthias Jung
  */
 
 /**
@@ -862,7 +863,7 @@ class DRAMCtrl : public AbstractMemory
      */
     static bool sortTime(const Data::MemCommand& m1,
                          const Data::MemCommand& m2) {
-        return m1.getTime() < m2.getTime();
+        return m1.getTimeInt64() < m2.getTimeInt64();
     };