From 86e9a6ffecbeb1ba743c71786e934cf290bab7ff Mon Sep 17 00:00:00 2001 From: Matthias Jung Date: Fri, 1 Jul 2016 10:31:36 -0500 Subject: [PATCH] ext: Update DRAMPower 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 --- ext/drampower/README.md | 4 +- ext/drampower/src/CmdScheduler.cc | 212 +++++------ ext/drampower/src/CmdScheduler.h | 80 ++--- ext/drampower/src/CommandAnalysis.cc | 290 +++++++-------- ext/drampower/src/CommandAnalysis.h | 29 +- ext/drampower/src/MemArchitectureSpec.h | 20 +- ext/drampower/src/MemCommand.cc | 43 +-- ext/drampower/src/MemCommand.h | 42 ++- ext/drampower/src/MemTimingSpec.h | 62 ++-- ext/drampower/src/MemoryPowerModel.cc | 331 ++++++++---------- ext/drampower/src/MemoryPowerModel.h | 12 +- ext/drampower/src/MemorySpecification.h | 11 +- ext/drampower/src/TraceParser.cc | 21 +- ext/drampower/src/TraceParser.h | 1 + ext/drampower/src/Utils.h | 4 +- .../src/libdrampower/LibDRAMPower.cc | 9 +- ext/drampower/src/libdrampower/LibDRAMPower.h | 2 + .../test/libdrampowertest/lib_test.cc | 5 +- src/mem/dram_ctrl.hh | 3 +- 19 files changed, 558 insertions(+), 623 deletions(-) diff --git a/ext/drampower/README.md b/ext/drampower/README.md index a43298b01..5d6eb6e82 100644 --- a/ext/drampower/README.md +++ b/ext/drampower/README.md @@ -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 ``` diff --git a/ext/drampower/src/CmdScheduler.cc b/ext/drampower/src/CmdScheduler.cc index bffc5d3bb..a4619b94e 100644 --- a/ext/drampower/src/CmdScheduler.cc +++ b/ext/drampower/src/CmdScheduler.cc @@ -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" @@ -42,17 +42,20 @@ #include // 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(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(i); cmd.name = "PRE"; - if (memSpec.id == "WIDEIO_SDR") - cmd.time = 1 - static_cast(memSpec.memTimingSpec.TAW); - else - cmd.time = 1 - static_cast(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(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(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 bankPointer(nbrOfBankGroups, 0); - std::vector bankAccessNum(nBanks, -1); - std::vector ACTSchedule(nBanks, false); - int bankAddr = -1; - double endTime = 0; - double tComing_REF = 0; + std::vector bankPointer(static_cast(nbrOfBankGroups), 0); + std::vector bankAccessNum(static_cast(nBanks), -1); + std::vector ACTSchedule(static_cast(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(memTimingSpec.RP)); + endTime = max(transFinish.time, PRE[static_cast(transFinish.bank)].time + + static_cast(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(memTimingSpec.RP)), tREF), startTime); - if (((power_down == SELF_REFRESH) && !Inselfrefresh) || - (power_down != SELF_REFRESH)) { + cmd.time = max(max(max(transFinish.time, PRE[static_cast(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(j); + bankAddr = bankGroupAddr * static_cast(nBanks) / nbrOfBankGroups + bankPointer[bankGroupAddr]; } else { bankAddr = Bs + i; } @@ -312,7 +316,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec) static_cast(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(ACT.size() - 1); ACTBank >= 0; ACTBank--) { - if (ACT[ACTBank].bank == bankAddr) { + if (ACT[ACTBank].bank == static_cast(bankAddr)) { cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time + static_cast(memTimingSpec.RCD)); break; @@ -392,7 +396,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec) PRE[bankAddr].name = "PRE"; for (int ACTBank = static_cast(ACT.size() - 1); ACTBank >= 0; ACTBank--) { - if (ACT[ACTBank].bank == bankAddr) { + if (ACT[ACTBank].bank == static_cast(bankAddr)) { PRE[bankAddr].time = max(ACT.back().time + static_cast(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(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(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(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(log2(nColumns)); - unsigned bankShift = static_cast(colBits + ((BI > 1) ? log2(BI) : 0) - + ((BGI > 1) ? log2(BGI) : 0)); - unsigned bankMask = static_cast(nBanks / (BI * nbrOfBankGroups) - 1) - << bankShift; - unsigned bankAddr = (DecLogic & bankMask) >> - static_cast(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(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(log2(BC * burstLength) + - ((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0)); - unsigned colMask = static_cast(nColumns / (BC * burstLength) - 1) - << colShift; - unsigned colAddr = (DecLogic & colMask) >> - static_cast((colShift - log2(static_cast(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(BC) * burstLength)); PhysicalAddr.colAddr = colAddr; } else { - unsigned colBits = static_cast(log2(nColumns)); - unsigned bankShift = static_cast(colBits + ((BI > 1) ? log2(BI) : 0)); - unsigned bankMask = static_cast(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(log2(BC * burstLength) + - ((BI > 1) ? log2(BI) : 0)); - unsigned colMask = static_cast(nColumns / (BC * burstLength) - 1) - << colShift; - unsigned colAddr = (DecLogic & colMask) >> - static_cast((colShift - log2(static_cast(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(log2(nColumns * nBanks)); - unsigned rowMask = static_cast(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(log2(in)); +} \ No newline at end of file diff --git a/ext/drampower/src/CmdScheduler.h b/ext/drampower/src/CmdScheduler.h index 3c60ea886..58efd279b 100644 --- a/ext/drampower/src/CmdScheduler.h +++ b/ext/drampower/src/CmdScheduler.h @@ -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 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 cmdScheduling; std::vector 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. diff --git a/ext/drampower/src/CommandAnalysis.cc b/ext/drampower/src/CommandAnalysis.cc index 4dea5c101..e557c2920 100644 --- a/ext/drampower/src/CommandAnalysis.cc +++ b/ext/drampower/src/CommandAnalysis.cc @@ -45,13 +45,34 @@ 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(nbrofBanks), 0); + last_states.resize(static_cast(nbrofBanks)); + mem_state = 0; + num_active_banks = 0; + + cmd_list.clear(); + cached_cmd.clear(); + activation_cycle.resize(static_cast(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& list, bool lastupdate) + std::vector& list, bool lastupdate) { - for (vector::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(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(memTimingSpec.RL + + offset = memTimingSpec.RL + memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength / - memArchSpec.dataRate)); + memArchSpec.dataRate); } else if (type == MemCommand::WR) { - offset = static_cast(memTimingSpec.WL + + offset = memTimingSpec.WL + (memArchSpec.burstLength / memArchSpec.dataRate) + - memTimingSpec.WR); + memTimingSpec.WR; } else if (type == MemCommand::ACT) { - offset = static_cast(memTimingSpec.RCD); + offset = memTimingSpec.RCD; } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) { - offset = static_cast(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& cmd_list, int nbrofBanks) + vector& 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(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(bank)] == 1) { printWarning("Bank is already active!", type, timestamp, bank); } - bankstate[bank] = 1; - if (mem_state == 0) { + bankstate[static_cast(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(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(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(bank)] == 1) { numberofpres++; } - bankstate[bank] = 0; + bankstate[static_cast(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(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); } } diff --git a/ext/drampower/src/CommandAnalysis.h b/ext/drampower/src/CommandAnalysis.h index b5c7ac778..15261fb2f 100644 --- a/ext/drampower/src/CommandAnalysis.h +++ b/ext/drampower/src/CommandAnalysis.h @@ -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& list, bool lastupdate); private: - unsigned init; int64_t zero; - unsigned pop; // Cached last read command from the file std::vector cached_cmd; // Stores the memory commands for analysis std::vector cmd_list; - // Stores all memory commands for analysis - std::vector full_cmd_list; - // To save states of the different banks, before entering active // power-down mode (slow/fast-exit). std::vector 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& cmd_list, - int nbrofBanks); + std::vector& 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); }; } diff --git a/ext/drampower/src/MemArchitectureSpec.h b/ext/drampower/src/MemArchitectureSpec.h index ca79edc91..49eddc8ac 100644 --- a/ext/drampower/src/MemArchitectureSpec.h +++ b/ext/drampower/src/MemArchitectureSpec.h @@ -31,13 +31,15 @@ * 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 + #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; diff --git a/ext/drampower/src/MemCommand.cc b/ext/drampower/src/MemCommand.cc index 156716c2f..5e1115e05 100644 --- a/ext/drampower/src/MemCommand.cc +++ b/ext/drampower/src/MemCommand.cc @@ -44,15 +44,9 @@ 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(memSpec.memArchSpec.burstLength)); - int RTP(static_cast(memSpec.memTimingSpec.RTP)); - int dataRate(static_cast(memSpec.memArchSpec.dataRate)); - int AL(static_cast(memSpec.memTimingSpec.AL)); - int WL(static_cast(memSpec.memTimingSpec.WL)); - int WR(static_cast(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(timestamp); + return timestamp; } MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const diff --git a/ext/drampower/src/MemCommand.h b/ext/drampower/src/MemCommand.h index ea7164577..9eb751088 100644 --- a/ext/drampower/src/MemCommand.h +++ b/ext/drampower/src/MemCommand.h @@ -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 diff --git a/ext/drampower/src/MemTimingSpec.h b/ext/drampower/src/MemTimingSpec.h index 1c3a80c6e..104bf5c71 100644 --- a/ext/drampower/src/MemTimingSpec.h +++ b/ext/drampower/src/MemTimingSpec.h @@ -31,10 +31,12 @@ * 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 + #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; }; } diff --git a/ext/drampower/src/MemoryPowerModel.cc b/ext/drampower/src/MemoryPowerModel.cc index 4817d1bb5..e020830e6 100644 --- a/ext/drampower/src/MemoryPowerModel.cc +++ b/ext/drampower/src/MemoryPowerModel.cc @@ -37,23 +37,24 @@ #include "MemoryPowerModel.h" -#include // For pow - #include +#include // For pow +#include // 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(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(counters.sref_cycles), static_cast(counters.sref_ref_act_cycles), - static_cast(counters.sref_ref_pre_cycles), static_cast(counters.spup_ref_act_cycles), - static_cast(counters.spup_ref_pre_cycles), t.clkPeriod); + static_cast(c.sref_cycles), static_cast(c.sref_ref_act_cycles), + static_cast(c.sref_ref_pre_cycles), static_cast(c.spup_ref_act_cycles), + static_cast(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(counters.sref_cycles), static_cast(counters.sref_ref_act_cycles), - static_cast(counters.sref_ref_pre_cycles), static_cast(counters.spup_ref_act_cycles), - static_cast(counters.spup_ref_pre_cycles), t.clkPeriod); + static_cast(c.sref_cycles), static_cast(c.sref_ref_act_cycles), + static_cast(c.sref_ref_pre_cycles), static_cast(c.spup_ref_act_cycles), + static_cast(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(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(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(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(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 diff --git a/ext/drampower/src/MemoryPowerModel.h b/ext/drampower/src/MemoryPowerModel.h index b894f67dd..2b2304989 100644 --- a/ext/drampower/src/MemoryPowerModel.h +++ b/ext/drampower/src/MemoryPowerModel.h @@ -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; diff --git a/ext/drampower/src/MemorySpecification.h b/ext/drampower/src/MemorySpecification.h index 149d41c28..16d77ef86 100644 --- a/ext/drampower/src/MemorySpecification.h +++ b/ext/drampower/src/MemorySpecification.h @@ -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) { diff --git a/ext/drampower/src/TraceParser.cc b/ext/drampower/src/TraceParser.cc index ec87f06da..2cf9a8572 100644 --- a/ext/drampower/src/TraceParser.cc +++ b/ext/drampower/src/TraceParser.cc @@ -42,14 +42,19 @@ 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(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(); diff --git a/ext/drampower/src/TraceParser.h b/ext/drampower/src/TraceParser.h index cabfcd395..9727b4800 100644 --- a/ext/drampower/src/TraceParser.h +++ b/ext/drampower/src/TraceParser.h @@ -48,6 +48,7 @@ class TraceParser { public: + TraceParser(int64_t nbrOfBanks); // list of parsed commands std::vector cmd_list; diff --git a/ext/drampower/src/Utils.h b/ext/drampower/src/Utils.h index 4aa8bb220..80f4390c7 100644 --- a/ext/drampower/src/Utils.h +++ b/ext/drampower/src/Utils.h @@ -41,9 +41,7 @@ #include #include #include -#include -#define MILLION 1000000 template 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; diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.cc b/ext/drampower/src/libdrampower/LibDRAMPower.cc index ac16f948b..47ed15a99 100644 --- a/ext/drampower/src/libdrampower/LibDRAMPower.cc +++ b/ext/drampower/src/libdrampower/LibDRAMPower.cc @@ -52,13 +52,13 @@ libDRAMPower::~libDRAMPower() void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp) { - MemCommand cmd(type, static_cast(bank), static_cast(timestamp)); + MemCommand cmd(type, static_cast(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; diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.h b/ext/drampower/src/libdrampower/LibDRAMPower.h index 9dea8b0f5..4d9ccefe5 100644 --- a/ext/drampower/src/libdrampower/LibDRAMPower.h +++ b/ext/drampower/src/libdrampower/LibDRAMPower.h @@ -56,6 +56,8 @@ class libDRAMPower { void updateCounters(bool lastUpdate); + void clearCounters(int64_t timestamp); + void clearState(); void calcEnergy(); diff --git a/ext/drampower/test/libdrampowertest/lib_test.cc b/ext/drampower/test/libdrampowertest/lib_test.cc index f382a727e..20d4d9ebf 100644 --- a/ext/drampower/test/libdrampowertest/lib_test.cc +++ b/ext/drampower/test/libdrampowertest/lib_test.cc @@ -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(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; diff --git a/src/mem/dram_ctrl.hh b/src/mem/dram_ctrl.hh index 6cd72b266..f59528492 100644 --- a/src/mem/dram_ctrl.hh +++ b/src/mem/dram_ctrl.hh @@ -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(); }; -- 2.30.2