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 <jason@lowepower.com>
This commit is contained in:
Matthias Jung 2016-07-01 10:31:36 -05:00
parent 137e244bda
commit 86e9a6ffec
19 changed files with 561 additions and 626 deletions

View 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:** **To cite the DRAMPower Tool:**
``` ```
[1] "DRAMPower: Open-source DRAM power & energy estimation tool" [1] DRAMPower: Open-source DRAM Power & Energy Estimation Tool
Karthik Chandrasekar, Christian Weis, Yonghui Li, Benny Akesson, Norbert Wehn, and Kees Goossens Karthik Chandrasekar, Christian Weis, Yonghui Li, Sven Goossens, Matthias Jung, Omar Naji, Benny Akesson, Norbert Wehn, and Kees Goossens
URL: http://www.drampower.info URL: http://www.drampower.info
``` ```

View file

@ -31,7 +31,7 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Karthik Chandrasekar * Authors: Karthik Chandrasekar, Yonghui Li, Sven Goossens
* *
*/ */
#include "CmdScheduler.h" #include "CmdScheduler.h"
@ -42,17 +42,20 @@
#include <algorithm> // For max #include <algorithm> // For max
#define MILLION 1000000
using namespace std; using namespace std;
using namespace Data; using namespace Data;
// Read the traces and get the transaction. Each transaction is executed by // Read the traces and get the transaction. Each transaction is executed by
// scheduling a number of commands to the memory. Hence, the transactions are // 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. // 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) ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
{ {
commands.open("commands.trace", ifstream::out); commands.open("commands.trace", ifstream::out);
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
nBanks = memArchSpec.nbrOfBanks; nBanks = memArchSpec.nbrOfBanks;
nColumns = memArchSpec.nbrOfColumns; nColumns = memArchSpec.nbrOfColumns;
burstLength = memArchSpec.burstLength; burstLength = memArchSpec.burstLength;
@ -77,13 +80,14 @@ void cmdScheduler::transTranslation(MemorySpecification memSpec,
} // cmdScheduler::transTranslation } // cmdScheduler::transTranslation
// initialize the variables and vectors for starting command scheduling. // 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); const size_t numBanks = static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks);
RDWR.resize(2 * memSpec.memArchSpec.nbrOfBanks); ACT.resize(2 * numBanks);
PRE.resize(memSpec.memArchSpec.nbrOfBanks); RDWR.resize(2 * numBanks);
PRE.resize(numBanks);
bankaccess = memSpec.memArchSpec.nbrOfBanks; bankaccess = memSpec.memArchSpec.nbrOfBanks;
if (!ACT.empty()) { if (!ACT.empty()) {
ACT.erase(ACT.begin(), ACT.end()); ACT.erase(ACT.begin(), ACT.end());
@ -96,14 +100,15 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
} }
///////////////initialization////////////// ///////////////initialization//////////////
for (unsigned i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) { for (int64_t i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
cmd.Type = PRECHARGE; cmd.Type = PRECHARGE;
cmd.bank = i; cmd.bank = static_cast<unsigned>(i);
cmd.name = "PRE"; cmd.name = "PRE";
if (memSpec.id == "WIDEIO_SDR") if (memSpec.id == "WIDEIO_SDR") {
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.TAW); cmd.time = 1 - memSpec.memTimingSpec.TAW;
else } else {
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.FAW); cmd.time = 1 - memSpec.memTimingSpec.FAW;
}
PRE.push_back(cmd); PRE.push_back(cmd);
@ -114,7 +119,7 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
cmd.Type = WRITE; cmd.Type = WRITE;
cmd.name = "WRITE"; cmd.name = "WRITE";
cmd.time = -1; cmd.time = -1;
RDWR[i].push_back(cmd); RDWR[static_cast<size_t>(i)].push_back(cmd);
} }
tREF = memTimingSpec.REFI; tREF = memTimingSpec.REFI;
transFinish.time = 0; transFinish.time = 0;
@ -130,14 +135,14 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
// transactions are generated according to the information read from the traces. // transactions are generated according to the information read from the traces.
// Then the command scheduling function is triggered to generate commands and // Then the command scheduling function is triggered to generate commands and
// schedule them to the memory according to the timing constraints. // 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; std::string line;
transTime = 0; transTime = 0;
unsigned newtranstime; uint64_t newtranstime;
unsigned transAddr; uint64_t transAddr;
unsigned transType = 1; int64_t transType = 1;
trans TransItem; trans TransItem;
if (!transTrace.empty()) { if (!transTrace.empty()) {
@ -147,12 +152,12 @@ void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memS
while (getline(trans_trace, line)) { while (getline(trans_trace, line)) {
istringstream linestream(line); istringstream linestream(line);
string item; string item;
unsigned itemnum = 0; uint64_t itemnum = 0;
while (getline(linestream, item, ',')) { while (getline(linestream, item, ',')) {
if (itemnum == 0) { if (itemnum == 0) {
stringstream timestamp(item); stringstream timestamp(item);
timestamp >> newtranstime; timestamp >> newtranstime;
transTime = transTime + newtranstime; transTime = transTime + static_cast<int64_t>(newtranstime);
} else if (itemnum == 1) { } else if (itemnum == 1) {
if (item == "write" || item == "WRITE") { if (item == "write" || item == "WRITE") {
transType = 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. // 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 // After the scheduling, a sequence of commands are obtained and they are written
// into commands.txt which will be used for power analysis. // into commands.txt which will be used for power analysis.
void cmdScheduler::analyticalScheduling(MemorySpecification memSpec) void cmdScheduler::analyticalScheduling(const MemorySpecification& memSpec)
{ {
int Bs = -1; int64_t transType = -1;
int transType = -1; int64_t timer = 0;
double timer = 0; uint64_t bankGroupPointer = 0;
int bankGroupPointer = 0; uint64_t bankGroupAddr = 0;
int bankGroupAddr = 0;
bool collisionFound; bool collisionFound;
physicalAddr PhysicalAddress; physicalAddr PhysicalAddress;
bool bankGroupSwitch = false; bool bankGroupSwitch = false;
std::vector<unsigned> bankPointer(nbrOfBankGroups, 0); std::vector<uint64_t> bankPointer(static_cast<size_t>(nbrOfBankGroups), 0);
std::vector<int> bankAccessNum(nBanks, -1); std::vector<int64_t> bankAccessNum(static_cast<size_t>(nBanks), -1);
std::vector<bool> ACTSchedule(nBanks, false); std::vector<bool> ACTSchedule(static_cast<size_t>(nBanks), false);
int bankAddr = -1; uint64_t bankAddr = 0;
double endTime = 0; int64_t endTime = 0;
double tComing_REF = 0; int64_t tComing_REF = 0;
Inselfrefresh = 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()); cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
for (unsigned i = 0; i < nBanks; i++) { for (auto a : ACTSchedule) {
ACTSchedule[i] = false; a = false;
bankAccessNum[i] = -1; }
for (auto& b : bankAccessNum) {
b = -1;
} }
timingsGet = false; timingsGet = false;
@ -225,12 +232,12 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
PhysicalAddress = memoryMap(transTrace[t], memSpec); PhysicalAddress = memoryMap(transTrace[t], memSpec);
for (unsigned i = 0; i < nbrOfBankGroups; i++) { for (auto& b : bankPointer) {
bankPointer[i] = PhysicalAddress.bankAddr; // the bank pointer per group. b = PhysicalAddress.bankAddr; // the bank pointer per group.
} }
bankGroupPointer = PhysicalAddress.bankGroupAddr; bankGroupPointer = PhysicalAddress.bankGroupAddr;
endTime = max(transFinish.time, PRE[transFinish.bank].time + endTime = max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time +
static_cast<int>(memTimingSpec.RP)); static_cast<int>(memTimingSpec.RP));
// Before starting the scheduling for the next transaction, it has to // Before starting the scheduling for the next transaction, it has to
@ -244,14 +251,12 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
///////////////Scheduling Refresh//////////////////////// ///////////////Scheduling Refresh////////////////////////
if (((transFinish.time >= tREF) || (timer >= tREF))) { 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++) { memTimingSpec.REFI : 0); i++) {
cmd.bank = 0; cmd.bank = 0;
cmd.name = "REF"; cmd.name = "REF";
cmd.time = max(max(max(transFinish.time, PRE[transFinish.bank].time cmd.time = max(max(max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time + memTimingSpec.RP), tREF), startTime);
+ static_cast<int>(memTimingSpec.RP)), tREF), startTime); if ((power_down == SELF_REFRESH && !Inselfrefresh) || power_down != SELF_REFRESH) {
if (((power_down == SELF_REFRESH) && !Inselfrefresh) ||
(power_down != SELF_REFRESH)) {
cmdScheduling.push_back(cmd); cmdScheduling.push_back(cmd);
startTime = cmd.time + memTimingSpec.RFC; startTime = cmd.time + memTimingSpec.RFC;
} }
@ -262,7 +267,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
} }
} }
///////////////Execution Transactions/////////////////// ///////////////Execution Transactions///////////////////
Bs = PhysicalAddress.bankAddr; uint64_t Bs = PhysicalAddress.bankAddr;
transType = transTrace[t].type; transType = transTrace[t].type;
tRWTP = getRWTP(transType, memSpec); tRWTP = getRWTP(transType, memSpec);
@ -280,9 +285,8 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
bankGroupSwitch = true; bankGroupSwitch = true;
} }
// update to the current bank group address. // update to the current bank group address.
bankGroupAddr = PhysicalAddress.bankGroupAddr + j; bankGroupAddr = PhysicalAddress.bankGroupAddr + static_cast<uint64_t>(j);
bankAddr = bankGroupAddr * nBanks / nbrOfBankGroups + bankAddr = bankGroupAddr * static_cast<uint64_t>(nBanks) / nbrOfBankGroups + bankPointer[bankGroupAddr];
bankPointer[bankGroupAddr];
} else { } else {
bankAddr = Bs + i; bankAddr = Bs + i;
} }
@ -312,7 +316,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
static_cast<int>(memTimingSpec.TAW)); 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, PreRDWR.time + 1);
cmd.time = max(cmd.time, timer); cmd.time = max(cmd.time, timer);
cmd.time = max(startTime, cmd.time); cmd.time = max(startTime, cmd.time);
@ -358,7 +362,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
} }
for (int ACTBank = static_cast<int>(ACT.size() - 1); for (int ACTBank = static_cast<int>(ACT.size() - 1);
ACTBank >= 0; ACTBank--) { 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 cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
+ static_cast<int>(memTimingSpec.RCD)); + static_cast<int>(memTimingSpec.RCD));
break; break;
@ -392,7 +396,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
PRE[bankAddr].name = "PRE"; PRE[bankAddr].name = "PRE";
for (int ACTBank = static_cast<int>(ACT.size() - 1); for (int ACTBank = static_cast<int>(ACT.size() - 1);
ACTBank >= 0; ACTBank--) { ACTBank >= 0; ACTBank--) {
if (ACT[ACTBank].bank == bankAddr) { if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
PRE[bankAddr].time = max(ACT.back().time + PRE[bankAddr].time = max(ACT.back().time +
static_cast<int>(memTimingSpec.RAS), static_cast<int>(memTimingSpec.RAS),
PreRDWR.time + tRWTP); PreRDWR.time + tRWTP);
@ -419,7 +423,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
/////////////Update Vector Length///////////////// /////////////Update Vector Length/////////////////
// the vector length is reduced so that less memory is used for running // the vector length is reduced so that less memory is used for running
// this tool. // 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++) { for (int m = 0; m < BI * BGI; m++) {
ACT.erase(ACT.begin()); ACT.erase(ACT.begin());
RDWR[0].erase(RDWR[0].begin(), RDWR[0].end()); 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. // 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 // It is called when the command scheduling for a transaction is finished, and it
// is also called if there is a refresh. // is also called if there is a refresh.
void cmdScheduler::pdScheduling(double endTime, double timer, void cmdScheduler::pdScheduling(int64_t endTime, int64_t timer,
MemorySpecification memSpec) const MemorySpecification& memSpec)
{ {
double ZERO = 0; int64_t ZERO = 0;
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
endTime = max(endTime, startTime); 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)) { if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
cmd.bank = 0; 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. // get the time when a precharge occurs after a read/write command is scheduled.
// In addition, it copes with different kind of memories. // 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; int64_t tRWTP_init = 0;
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (transType == READ) { if (transType == READ) {
switch (memSpec.memoryType) { switch (memSpec.memoryType) {
@ -506,13 +510,13 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
case MemoryType::LPDDR2: case MemoryType::LPDDR2:
case MemoryType::LPDDR3: case MemoryType::LPDDR3:
tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate + tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
max(0, static_cast<int>(memTimingSpec.RTP - 2)); max(int64_t(0), memTimingSpec.RTP - 2);
break; break;
case MemoryType::DDR2: case MemoryType::DDR2:
tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength / tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
memArchSpec.dataRate + memArchSpec.dataRate +
max(static_cast<int>(memTimingSpec.RTP), 2) - 2; max(memTimingSpec.RTP, int64_t(2)) - 2;
break; break;
case MemoryType::DDR3: case MemoryType::DDR3:
@ -525,10 +529,10 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
} else if (transType == WRITE) { } else if (transType == WRITE) {
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) { if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength / tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate - 1 + memSpec.memTimingSpec.WR; memArchSpec.dataRate - 1 + memTimingSpec.WR;
} else { } else {
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength / tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate + memSpec.memTimingSpec.WR; memArchSpec.dataRate + memTimingSpec.WR;
} }
if ((memSpec.memoryType == MemoryType::LPDDR2) || if ((memSpec.memoryType == MemoryType::LPDDR2) ||
(memSpec.memoryType == MemoryType::LPDDR3)) { (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 // 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 // scheduling a read/write command after a read/write command which have been
// scheduled to any possible banks within any possible bank groups (DDR4). // scheduled to any possible banks within any possible bank groups (DDR4).
void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSpec, void cmdScheduler::getTimingConstraints(bool BGSwitch, const MemorySpecification& memSpec,
int PreType, int CurrentType) int64_t PreType, int64_t CurrentType)
{ {
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (memSpec.memoryType != MemoryType::DDR4) { if (memSpec.memoryType != MemoryType::DDR4) {
tRRD_init = memTimingSpec.RRD; tRRD_init = memTimingSpec.RRD;
@ -586,7 +590,7 @@ void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSp
if (PreType == CurrentType) { if (PreType == CurrentType) {
tSwitch_init = tCCD_init; tSwitch_init = tCCD_init;
timingsGet = true; timingsGet = true;
} else if ((PreType == WRITE) && (CurrentType == READ)) { } else if (PreType == WRITE && CurrentType == READ) {
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength / tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
memArchSpec.dataRate + tWTR_init; 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 // The logical address of each transaction is translated into a physical address
// which consists of bank group (for DDR4), bank, row and column addresses. // which consists of bank group (for DDR4), bank, row and column addresses.
cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans, cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans,
MemorySpecification memSpec) const MemorySpecification& memSpec)
{ {
int DecLogic; int64_t DecLogic;
physicalAddr PhysicalAddr; physicalAddr PhysicalAddr;
DecLogic = Trans.logicalAddress; DecLogic = Trans.logicalAddress;
// row-bank-column-BI-BC-BGI-BL // row-bank-column-BI-BC-BGI-BL
if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) { if (BGI > 1 && memSpec.memoryType == MemoryType::DDR4) {
unsigned colBits = static_cast<unsigned>(log2(nColumns)); uint64_t colBits = uintLog2(nColumns);
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0) uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
+ ((BGI > 1) ? log2(BGI) : 0)); uint64_t bankMask = (nBanks / (BI * nbrOfBankGroups) - 1) << bankShift;
unsigned bankMask = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1) uint64_t bankAddr = (DecLogic & bankMask) >> (colBits + ((BGI > 1) ? uintLog2(BGI) : 0));
<< bankShift;
unsigned bankAddr = (DecLogic & bankMask) >>
static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0));
PhysicalAddr.bankAddr = bankAddr; PhysicalAddr.bankAddr = bankAddr;
unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength)); uint64_t bankGroupShift = uintLog2(burstLength);
unsigned bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift; uint64_t bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
unsigned bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift; uint64_t bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
PhysicalAddr.bankGroupAddr = bankGroupAddr; PhysicalAddr.bankGroupAddr = bankGroupAddr;
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) + uint64_t colShift = uintLog2(BC * burstLength) +
((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0)); ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1) uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
<< colShift; uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(static_cast<uint64_t>(BC) * burstLength));
unsigned colAddr = (DecLogic & colMask) >>
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
PhysicalAddr.colAddr = colAddr; PhysicalAddr.colAddr = colAddr;
} else { } else {
unsigned colBits = static_cast<unsigned>(log2(nColumns)); uint64_t colBits = uintLog2(nColumns);
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)); uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0);
unsigned bankMask = static_cast<unsigned>(nBanks / BI - 1) << bankShift; uint64_t bankMask = (nBanks / BI - 1) << bankShift;
unsigned bankAddr = (DecLogic & bankMask) >> colBits; uint64_t bankAddr = (DecLogic & bankMask) >> colBits;
PhysicalAddr.bankAddr = bankAddr; PhysicalAddr.bankAddr = bankAddr;
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) + uint64_t colShift = (uintLog2(BC * burstLength) + ((BI > 1) ? uintLog2(BI) : 0));
((BI > 1) ? log2(BI) : 0)); uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1) uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(BC * burstLength));
<< colShift;
unsigned colAddr = (DecLogic & colMask) >>
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
PhysicalAddr.colAddr = colAddr; PhysicalAddr.colAddr = colAddr;
PhysicalAddr.bankGroupAddr = 0; PhysicalAddr.bankGroupAddr = 0;
} }
unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks)); uint64_t rowShift = uintLog2(nColumns * nBanks);
unsigned rowMask = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1) uint64_t rowMask = (memSpec.memArchSpec.nbrOfRows - 1) << rowShift;
<< rowShift; uint64_t rowAddr = (DecLogic & rowMask) >> rowShift;
unsigned rowAddr = (DecLogic & rowMask) >> rowShift;
PhysicalAddr.rowAddr = rowAddr; PhysicalAddr.rowAddr = rowAddr;
return PhysicalAddr; return PhysicalAddr;
} // cmdScheduler::memoryMap } // cmdScheduler::memoryMap
uint64_t cmdScheduler::uintLog2(uint64_t in)
{
return static_cast<uint64_t>(log2(in));
}

View file

@ -59,9 +59,9 @@ class cmdScheduler {
// the format of a transaction. // the format of a transaction.
class trans { class trans {
public: public:
int type; int64_t type;
double timeStamp; int64_t timeStamp;
unsigned logicalAddress; uint64_t logicalAddress;
}; };
std::vector<trans> transTrace; // to store the transactions. std::vector<trans> transTrace; // to store the transactions.
@ -69,18 +69,18 @@ class cmdScheduler {
// the format of physical address. // the format of physical address.
class physicalAddr { class physicalAddr {
public: public:
unsigned rowAddr; uint64_t rowAddr;
unsigned bankAddr; uint64_t bankAddr;
unsigned bankGroupAddr; uint64_t bankGroupAddr;
unsigned colAddr; uint64_t colAddr;
}; };
// the format of a command. // the format of a command.
class commandItem { class commandItem {
public: public:
int Type; int64_t Type;
int bank; int64_t bank;
double time; int64_t time;
std::string name; std::string name;
physicalAddr PhysicalAddr; physicalAddr PhysicalAddr;
// sorting the commands according to their scheduling time. // sorting the commands according to their scheduling time.
@ -107,11 +107,11 @@ class cmdScheduler {
std::vector<commandItem> cmdScheduling; std::vector<commandItem> cmdScheduling;
std::vector<commandItem> cmdList; std::vector<commandItem> cmdList;
unsigned elements; unsigned elements;
int BI, BC, BGI; int64_t BI, BC, BGI;
// the function used to translate a transaction into a sequence of // the function used to translate a transaction into a sequence of
// commands which are scheduled to the memory. // commands which are scheduled to the memory.
void transTranslation(Data::MemorySpecification memSpec, void transTranslation(const MemorySpecification& memSpec,
std::ifstream& trans_trace, std::ifstream& trans_trace,
int grouping, int grouping,
int interleaving, int interleaving,
@ -119,45 +119,47 @@ class cmdScheduler {
int powerdown); int powerdown);
// get the transactions by reading the traces. // get the transactions by reading the traces.
void getTrans(std::ifstream& pwr_trace, void getTrans(std::ifstream& pwr_trace,
MemorySpecification memSpec); const MemorySpecification& memSpec);
// the initialization function for scheduling. // 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. // 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. // translate the logical address into physical address.
physicalAddr memoryMap(trans Trans, physicalAddr memoryMap(trans Trans,
MemorySpecification memSpec); const MemorySpecification& memSpec);
// the power down and power up are scheduled by pdScheduling // the power down and power up are scheduled by pdScheduling
void pdScheduling(double endTime, void pdScheduling(int64_t endTime,
double timer, int64_t timer,
MemorySpecification memSpec); const MemorySpecification& memSpec);
// get the timings for scheduling a precharge since a read or write command // get the timings for scheduling a precharge since a read or write command
// is scheduled. // is scheduled.
int getRWTP(int transType, int64_t getRWTP(int64_t transType,
MemorySpecification memSpec); const MemorySpecification& memSpec);
// get different kind of timing constraints according to the used memory. // get different kind of timing constraints according to the used memory.
void getTimingConstraints(bool BGSwitch, void getTimingConstraints(bool BGSwitch,
MemorySpecification memSpec, const MemorySpecification& memSpec,
int PreType, int64_t PreType,
int CurrentType); int64_t CurrentType);
double transTime; uint64_t uintLog2(uint64_t in);
int64_t transTime;
// the flag for power down. // the flag for power down.
int power_down; int64_t power_down;
int Inselfrefresh; int64_t Inselfrefresh;
int tRRD_init; int64_t tRRD_init;
int tCCD_init; int64_t tCCD_init;
int tWTR_init; int64_t tWTR_init;
double tREF; int64_t tREF;
double tSwitch_init; int64_t tSwitch_init;
double tRWTP; int64_t tRWTP;
int bankaccess; int64_t bankaccess;
unsigned nBanks; int64_t nBanks;
unsigned nColumns; int64_t nColumns;
unsigned burstLength; int64_t burstLength;
unsigned nbrOfBankGroups; int64_t nbrOfBankGroups;
bool timingsGet; bool timingsGet;
double startTime; int64_t startTime;
// the scheduling results for all the transactions are written into // the scheduling results for all the transactions are written into
// commands which will be used by the power analysis part. // commands which will be used by the power analysis part.

View file

@ -45,13 +45,34 @@
using namespace Data; using namespace Data;
using namespace std; 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 // 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; numberofacts = 0;
numberofpres = 0; numberofpres = 0;
@ -64,10 +85,6 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
s_pre_pdns = 0; s_pre_pdns = 0;
numberofsrefs = 0; numberofsrefs = 0;
pop = 0;
init = 0;
zero = 0;
actcycles = 0; actcycles = 0;
precycles = 0; precycles = 0;
f_act_pdcycles = 0; f_act_pdcycles = 0;
@ -85,28 +102,29 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
idlecycles_act = 0; idlecycles_act = 0;
idlecycles_pre = 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_act_cycle = -1;
latest_pre_cycle = -1;
latest_read_cycle = -1; latest_read_cycle = -1;
latest_write_cycle = -1; latest_write_cycle = -1;
end_read_op = 0;
end_write_op = 0;
end_act_op = 0;
first_act_cycle = 0; if (timestamp == 0) {
last_pre_cycle = 0; // set to -1 at beginning of simulation
latest_pre_cycle = -1;
bankstate.resize(nbrofBanks, 0); } else {
last_states.resize(nbrofBanks); // NOTE: reference is adjusted by tRP (PRE delay) when updating counter
mem_state = 0; // could remove tRP to ensure counter starts at beginning of next block;
// currently simply setting to timestamp for simplicity
sref_cycle = 0; latest_pre_cycle = timestamp;
pdn_cycle = 0; }
cmd_list.clear();
full_cmd_list.resize(1, MemCommand::PRE);
cached_cmd.clear();
activation_cycle.resize(nbrofBanks, 0);
} }
// function to clear all arrays // function to clear all arrays
@ -114,7 +132,6 @@ void CommandAnalysis::clear()
{ {
cached_cmd.clear(); cached_cmd.clear();
cmd_list.clear(); cmd_list.clear();
full_cmd_list.clear();
last_states.clear(); last_states.clear();
bankstate.clear(); bankstate.clear();
} }
@ -125,132 +142,57 @@ void CommandAnalysis::clear()
// issued command timestamp, when the auto-precharge would kick in // issued command timestamp, when the auto-precharge would kick in
void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec, 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) { for (size_t i = 0; i < list.size(); ++i) {
const MemCommand& cmd = *i; MemCommand& cmd = list[i];
cmd_list.push_back(cmd);
MemCommand::cmds cmdType = cmd.getType(); MemCommand::cmds cmdType = cmd.getType();
if (cmdType == MemCommand::ACT) { if (cmdType == MemCommand::ACT) {
activation_cycle[cmd.getBank()] = cmd.getTimeInt64(); activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
} else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) { } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
// Remove auto-precharge flag from command // 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 // Add the auto precharge to the list of cached_cmds
int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType), int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS); 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; sort(list.begin(), list.end(), commandSorter);
// Note: the extra pre-cmds at the end of the lists, and the cast to double
// of the size vector is probably not desirable. if (lastupdate && list.empty() == false) {
cmd_list.push_back(MemCommand::PRE); // Add cycles at the end of the list
cached_cmd.push_back(MemCommand::PRE); int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1;
analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1, list.push_back(MemCommand(MemCommand::NOP, 0, t));
cached_cmd.size()-1, lastupdate); }
cmd_list.clear();
cached_cmd.clear(); evaluate(memSpec, list);
} // CommandAnalysis::getCommands } // 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.
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);
}
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, full_cmd_list, nbrofBanks);
} // CommandAnalysis::analyse_commands
// To get the time of completion of the issued command // To get the time of completion of the issued command
// Derived based on JEDEC specifications // Derived based on JEDEC specifications
int CommandAnalysis::timeToCompletion(const MemorySpecification& int64_t CommandAnalysis::timeToCompletion(const MemorySpecification&
memSpec, MemCommand::cmds type) memSpec, MemCommand::cmds type)
{ {
int offset = 0; int64_t offset = 0;
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (type == MemCommand::RD) { if (type == MemCommand::RD) {
offset = static_cast<int>(memTimingSpec.RL + offset = memTimingSpec.RL +
memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength / memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
memArchSpec.dataRate)); memArchSpec.dataRate);
} else if (type == MemCommand::WR) { } else if (type == MemCommand::WR) {
offset = static_cast<int>(memTimingSpec.WL + offset = memTimingSpec.WL +
(memArchSpec.burstLength / memArchSpec.dataRate) + (memArchSpec.burstLength / memArchSpec.dataRate) +
memTimingSpec.WR); memTimingSpec.WR;
} else if (type == MemCommand::ACT) { } else if (type == MemCommand::ACT) {
offset = static_cast<int>(memTimingSpec.RCD); offset = memTimingSpec.RCD;
} else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) { } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
offset = static_cast<int>(memTimingSpec.RP); offset = memTimingSpec.RP;
} }
return offset; return offset;
} // CommandAnalysis::timeToCompletion } // CommandAnalysis::timeToCompletion
@ -258,38 +200,39 @@ int CommandAnalysis::timeToCompletion(const MemorySpecification&
// Used to analyse a given list of commands and identify command timings // Used to analyse a given list of commands and identify command timings
// and memory state transitions // and memory state transitions
void CommandAnalysis::evaluate(const MemorySpecification& memSpec, 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 each command identify timestamp, type and bank
for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size(); for (auto cmd : cmd_list) {
cmd_list_counter++) {
// For command type // For command type
int type = cmd_list[cmd_list_counter].getType(); int type = cmd.getType();
// For command bank // 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) // 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) { 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 // If command is ACT - update number of acts, bank state of the
// target bank, first and latest activation cycle and the memory // target bank, first and latest activation cycle and the memory
// state. Update the number of precharged/idle-precharged cycles. // state. Update the number of precharged/idle-precharged cycles.
numberofacts++; numberofacts++;
if (bankstate[bank] == 1) { if (bankstate[static_cast<size_t>(bank)] == 1) {
printWarning("Bank is already active!", type, timestamp, bank); printWarning("Bank is already active!", type, timestamp, bank);
} }
bankstate[bank] = 1; bankstate[static_cast<size_t>(bank)] = 1;
if (mem_state == 0) { if (num_active_banks == 0) {
first_act_cycle = timestamp; first_act_cycle = timestamp;
precycles += max(zero, timestamp - last_pre_cycle); precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle); idle_pre_update(memSpec, timestamp, latest_pre_cycle);
} }
latest_act_cycle = timestamp; latest_act_cycle = timestamp;
mem_state++; num_active_banks++;
} else if (type == MemCommand::RD) { } 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 // If command is RD - update number of reads and read cycle. Check
// for active idle cycles (if any). // 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); printWarning("Bank is not active!", type, timestamp, bank);
} }
numberofreads++; numberofreads++;
@ -297,9 +240,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
latest_act_cycle, timestamp); latest_act_cycle, timestamp);
latest_read_cycle = timestamp; latest_read_cycle = timestamp;
} else if (type == MemCommand::WR) { } 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 // If command is WR - update number of writes and write cycle. Check
// for active idle cycles (if any). // 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); printWarning("Bank is not active!", type, timestamp, bank);
} }
numberofwrites++; numberofwrites++;
@ -307,6 +251,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
latest_act_cycle, timestamp); latest_act_cycle, timestamp);
latest_write_cycle = timestamp; latest_write_cycle = timestamp;
} else if (type == MemCommand::REF) { } 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 // 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 // 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 // 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; memSpec.memTimingSpec.RP;
latest_pre_cycle = last_pre_cycle; latest_pre_cycle = last_pre_cycle;
actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP; actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
mem_state = 0; num_active_banks = 0;
for (int j = 0; j < nbrofBanks; j++) { for (auto& b : bankstate) {
bankstate[j] = 0; b = 0;
} }
} else if (type == MemCommand::PRE) { } 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 // If command is explicit PRE - update number of precharges, bank
// state of the target bank and last and latest precharge cycle. // state of the target bank and last and latest precharge cycle.
// Calculate the number of active cycles if the memory was in the // Calculate the number of active cycles if the memory was in the
// active state before, but there is a state transition to PRE now. // active state before, but there is a state transition to PRE now.
// If not, update the number of precharged cycles and idle cycles. // If not, update the number of precharged cycles and idle cycles.
// Update memory state if needed. // Update memory state if needed.
if (bankstate[bank] == 1) { if (bankstate[static_cast<size_t>(bank)] == 1) {
numberofpres++; 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); actcycles += max(zero, timestamp - first_act_cycle);
last_pre_cycle = timestamp; last_pre_cycle = timestamp;
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp); latest_act_cycle, timestamp);
} else if (mem_state == 0) { } else if (num_active_banks == 0) {
precycles += max(zero, timestamp - last_pre_cycle); precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle); idle_pre_update(memSpec, timestamp, latest_pre_cycle);
last_pre_cycle = timestamp; last_pre_cycle = timestamp;
} }
latest_pre_cycle = timestamp; latest_pre_cycle = timestamp;
if (mem_state > 0) { if (num_active_banks > 0) {
mem_state--; num_active_banks--;
} else { } else {
mem_state = 0; num_active_banks = 0;
} }
} else if (type == MemCommand::PREA) { } 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 // If command is explicit PREA (precharge all banks) - update
// number of precharges by the number of banks, update the bank // number of precharges by the number of banks, update the bank
// state of all banks to PRE and set the precharge cycle. // state of all banks to PRE and set the precharge cycle.
// Calculate the number of active cycles if the memory was in the // Calculate the number of active cycles if the memory was in the
// active state before, but there is a state transition to PRE now. // active state before, but there is a state transition to PRE now.
// If not, update the number of precharged cycles and idle cycles. // If not, update the number of precharged cycles and idle cycles.
if (timestamp == 0) { numberofpres += num_active_banks;
numberofpres += 0;
} else {
numberofpres += mem_state;
}
if (mem_state > 0) { if (num_active_banks > 0) {
actcycles += max(zero, timestamp - first_act_cycle); actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp); latest_act_cycle, timestamp);
} else if (mem_state == 0) { } else if (num_active_banks == 0) {
precycles += max(zero, timestamp - last_pre_cycle); precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle); idle_pre_update(memSpec, timestamp, latest_pre_cycle);
} }
@ -378,10 +321,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
latest_pre_cycle = timestamp; latest_pre_cycle = timestamp;
last_pre_cycle = timestamp; last_pre_cycle = timestamp;
mem_state = 0; num_active_banks = 0;
for (int j = 0; j < nbrofBanks; j++) { for (auto& b : bankstate) {
bankstate[j] = 0; b = 0;
} }
} else if (type == MemCommand::PDN_F_ACT) { } else if (type == MemCommand::PDN_F_ACT) {
// If command is fast-exit active power-down - update number of // 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. // after powering-up. Update active and active idle cycles.
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank); printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
f_act_pdns++; f_act_pdns++;
for (int j = 0; j < nbrofBanks; j++) { last_states = bankstate;
last_states[j] = bankstate[j];
}
pdn_cycle = timestamp; pdn_cycle = timestamp;
actcycles += max(zero, timestamp - first_act_cycle); actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_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. // after powering-up. Update active and active idle cycles.
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank); printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
s_act_pdns++; s_act_pdns++;
for (int j = 0; j < nbrofBanks; j++) { last_states = bankstate;
last_states[j] = bankstate[j];
}
pdn_cycle = timestamp; pdn_cycle = timestamp;
actcycles += max(zero, timestamp - first_act_cycle); actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
@ -461,14 +400,14 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.XPDLL -
(2 * memSpec.memTimingSpec.RCD)); (2 * memSpec.memTimingSpec.RCD));
} }
} else if ((mem_state != CommandAnalysis::MS_PDN_S_ACT) || (mem_state != } else if (mem_state != CommandAnalysis::MS_PDN_S_ACT || mem_state != CommandAnalysis::MS_PDN_F_ACT) {
CommandAnalysis::MS_PDN_F_ACT)) {
cerr << "Incorrect use of Active Power-Up!" << endl; cerr << "Incorrect use of Active Power-Up!" << endl;
} }
num_active_banks = 0;
mem_state = 0; mem_state = 0;
for (int j = 0; j < nbrofBanks; j++) { bankstate = last_states;
bankstate[j] = last_states[j]; for (auto& a : last_states) {
mem_state += last_states[j]; num_active_banks += static_cast<unsigned int>(a);
} }
first_act_cycle = timestamp; first_act_cycle = timestamp;
} else if (type == MemCommand::PUP_PRE) { } else if (type == MemCommand::PUP_PRE) {
@ -493,11 +432,11 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD - memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
memSpec.memTimingSpec.RP); memSpec.memTimingSpec.RP);
} }
} else if ((mem_state != CommandAnalysis::MS_PDN_S_PRE) || (mem_state != } else if (mem_state != CommandAnalysis::MS_PDN_S_PRE || mem_state != CommandAnalysis::MS_PDN_F_PRE) {
CommandAnalysis::MS_PDN_F_PRE)) {
cerr << "Incorrect use of Precharged Power-Up!" << endl; cerr << "Incorrect use of Precharged Power-Up!" << endl;
} }
mem_state = 0; mem_state = 0;
num_active_banks = 0;
last_pre_cycle = timestamp; last_pre_cycle = timestamp;
} else if (type == MemCommand::SREN) { } else if (type == MemCommand::SREN) {
// If command is self-refresh - update number of self-refreshes, // If command is self-refresh - update number of self-refreshes,
@ -583,14 +522,15 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
} }
} }
mem_state = 0; 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 // May be optionally used at the end of memory trace for better accuracy
// Update all counters based on completion of operations. // 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); actcycles += max(zero, timestamp - first_act_cycle);
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
latest_act_cycle, timestamp); 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); precycles += max(zero, timestamp - last_pre_cycle);
idle_pre_update(memSpec, timestamp, latest_pre_cycle); idle_pre_update(memSpec, timestamp, latest_pre_cycle);
} else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) { } 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) { } else if (mem_state == CommandAnalysis::MS_SREF) {
sref_cycles += max(zero, timestamp - sref_cycle); sref_cycles += max(zero, timestamp - sref_cycle);
} }
} else {
printWarning("Unknown command given, exiting.", type, timestamp, bank);
exit(-1);
} }
} }
} // CommandAnalysis::evaluate } // 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) 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); printWarning(warning, type, timestamp, bank);
} }
} }
void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int 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); printWarning(warning, type, timestamp, bank);
} }
} }

View file

@ -58,10 +58,8 @@ class CommandAnalysis {
MS_PDN_S_PRE = 13, MS_SREF = 14 MS_PDN_S_PRE = 13, MS_SREF = 14
}; };
CommandAnalysis();
// Returns number of reads, writes, acts, pres and refs in the trace // 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 // Number of activate commands
int64_t numberofacts; int64_t numberofacts;
@ -117,29 +115,25 @@ class CommandAnalysis {
// Number of precharged auto-refresh cycles during self-refresh exit // Number of precharged auto-refresh cycles during self-refresh exit
int64_t spup_ref_pre_cycles; int64_t spup_ref_pre_cycles;
// function for clearing counters
void clearStats(const int64_t timestamp);
// function for clearing arrays // function for clearing arrays
void clear(); void clear();
// To identify auto-precharges // To identify auto-precharges
void getCommands(const MemorySpecification& memSpec, void getCommands(const MemorySpecification& memSpec,
const int
nbrofBanks,
std::vector<MemCommand>& list, std::vector<MemCommand>& list,
bool lastupdate); bool lastupdate);
private: private:
unsigned init;
int64_t zero; int64_t zero;
unsigned pop;
// Cached last read command from the file // Cached last read command from the file
std::vector<MemCommand> cached_cmd; std::vector<MemCommand> cached_cmd;
// Stores the memory commands for analysis // Stores the memory commands for analysis
std::vector<MemCommand> cmd_list; 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 // To save states of the different banks, before entering active
// power-down mode (slow/fast-exit). // power-down mode (slow/fast-exit).
std::vector<int> last_states; std::vector<int> last_states;
@ -171,26 +165,20 @@ class CommandAnalysis {
// Memory State // Memory State
unsigned mem_state; unsigned mem_state;
unsigned num_active_banks;
// Clock cycle of first activate command when memory state changes to ACT // Clock cycle of first activate command when memory state changes to ACT
int64_t first_act_cycle; int64_t first_act_cycle;
// Clock cycle of last precharge command when memory state changes to PRE // Clock cycle of last precharge command when memory state changes to PRE
int64_t last_pre_cycle; 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 // To perform timing analysis of a given set of commands and update command counters
void evaluate(const MemorySpecification& memSpec, void evaluate(const MemorySpecification& memSpec,
std::vector<MemCommand>& cmd_list, std::vector<MemCommand>& cmd_list);
int nbrofBanks);
// To calculate time of completion of any issued command // To calculate time of completion of any issued command
int timeToCompletion(const MemorySpecification& memSpec, int64_t timeToCompletion(const MemorySpecification& memSpec,
MemCommand::cmds type); MemCommand::cmds type);
// To update idle period information whenever active cycles may be idle // 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 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 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); void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
}; };
} }

View file

@ -31,13 +31,15 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Karthik Chandrasekar * Authors: Karthik Chandrasekar, Sven Goossens
* *
*/ */
#ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H #ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H
#define TOOLS_MEM_ARCHITECTURE_SPEC_H #define TOOLS_MEM_ARCHITECTURE_SPEC_H
#include <stdint.h>
#include "Parametrisable.h" #include "Parametrisable.h"
namespace Data { namespace Data {
@ -46,14 +48,14 @@ class MemArchitectureSpec : public virtual Parametrisable {
MemArchitectureSpec(); MemArchitectureSpec();
void processParameters(); void processParameters();
unsigned int burstLength; int64_t burstLength;
unsigned nbrOfBanks; int64_t nbrOfBanks;
unsigned nbrOfRanks; int64_t nbrOfRanks;
unsigned dataRate; int64_t dataRate;
unsigned nbrOfColumns; int64_t nbrOfColumns;
unsigned nbrOfRows; int64_t nbrOfRows;
unsigned width; int64_t width;
unsigned nbrOfBankGroups; int64_t nbrOfBankGroups;
bool dll; bool dll;
bool twoVoltageDomains; bool twoVoltageDomains;
bool termination; bool termination;

View file

@ -44,15 +44,9 @@
using namespace Data; using namespace Data;
using namespace std; using namespace std;
MemCommand::MemCommand() :
type(MemCommand::PRE),
bank(0),
timestamp(0)
{
}
MemCommand::MemCommand(MemCommand::cmds type, MemCommand::MemCommand(MemCommand::cmds type,
unsigned bank, double timestamp) : unsigned bank, int64_t timestamp) :
type(type), type(type),
bank(bank), bank(bank),
timestamp(timestamp) timestamp(timestamp)
@ -80,35 +74,35 @@ unsigned MemCommand::getBank() const
} }
// For auto-precharge with read or write - to calculate cycle of precharge // 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 MemCommand::cmds type) const
{ {
int precharge_offset = 0; int64_t precharge_offset = 0;
int BL(static_cast<int>(memSpec.memArchSpec.burstLength)); int64_t BL = memSpec.memArchSpec.burstLength;
int RTP(static_cast<int>(memSpec.memTimingSpec.RTP)); int64_t RTP = memSpec.memTimingSpec.RTP;
int dataRate(static_cast<int>(memSpec.memArchSpec.dataRate)); int64_t dataRate = memSpec.memArchSpec.dataRate;
int AL(static_cast<int>(memSpec.memTimingSpec.AL)); int64_t AL = memSpec.memTimingSpec.AL;
int WL(static_cast<int>(memSpec.memTimingSpec.WL)); int64_t WL = memSpec.memTimingSpec.WL;
int WR(static_cast<int>(memSpec.memTimingSpec.WR)); int64_t WR = memSpec.memTimingSpec.WR;
int B = BL/dataRate; int64_t B = BL/dataRate;
const MemoryType::MemoryType_t& memType = memSpec.memoryType; const MemoryType::MemoryType_t& memType = memSpec.memoryType;
// Read with auto-precharge // Read with auto-precharge
if (type == MemCommand::RDA) { if (type == MemCommand::RDA) {
if (memType == MemoryType::DDR2) { 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) { } else if (memType == MemoryType::DDR3) {
precharge_offset = AL + max(RTP, 4); precharge_offset = AL + max(RTP, int64_t(4));
} else if (memType == MemoryType::DDR4) { } else if (memType == MemoryType::DDR4) {
precharge_offset = AL + RTP; precharge_offset = AL + RTP;
} else if (memType == MemoryType::LPDDR) { } else if (memType == MemoryType::LPDDR) {
precharge_offset = B; precharge_offset = B;
} else if (memType == MemoryType::LPDDR2) { } 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) { } 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) { } else if (memType == MemoryType::WIDEIO_SDR) {
precharge_offset = B; precharge_offset = B;
} }
@ -133,19 +127,14 @@ int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
return precharge_offset; return precharge_offset;
} // MemCommand::getPrechargeOffset } // MemCommand::getPrechargeOffset
void MemCommand::setTime(double _timestamp) void MemCommand::setTime(int64_t _timestamp)
{ {
timestamp = _timestamp; timestamp = _timestamp;
} }
double MemCommand::getTime() const
{
return timestamp;
}
int64_t MemCommand::getTimeInt64() const int64_t MemCommand::getTimeInt64() const
{ {
return static_cast<int64_t>(timestamp); return timestamp;
} }
MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const

View file

@ -86,17 +86,18 @@ class MemCommand {
PUP_ACT = 14, PUP_ACT = 14,
SREN = 15, SREN = 15,
SREX = 16, SREX = 16,
NOP = 17 NOP = 17,
UNINITIALIZED = 18
}; };
MemCommand(); // MemCommand();
MemCommand( MemCommand(
// Command Type // Command Type
MemCommand::cmds type, MemCommand::cmds type = UNINITIALIZED,
// Target Bank // Target Bank
unsigned bank = 0, unsigned bank = 0,
// Command Issue Timestamp (in cc) // Command Issue Timestamp (in cc)
double timestamp = 0); int64_t timestamp = 0L);
// Get command type // Get command type
cmds getType() const; cmds getType() const;
@ -111,16 +112,15 @@ class MemCommand {
unsigned getBank() const; unsigned getBank() const;
// Set timestamp // Set timestamp
void setTime(double _timestamp); void setTime(int64_t _timestamp);
// Get timestamp // Get timestamp
double getTime() const;
int64_t getTimeInt64() const; int64_t getTimeInt64() const;
cmds typeWithoutAutoPrechargeFlag() const; cmds typeWithoutAutoPrechargeFlag() const;
// To calculate precharge offset after read or write with auto-precharge // 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; MemCommand::cmds type) const;
// To check for equivalence // 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* getCommandTypeStrings()
{ {
static std::string type_map[nCommands] = { "ACT", "RD", "WR", "PRE", "REF", static std::string type_map[nCommands] = { "ACT",
"END", "RDA", "WRA", "PREA", "PDN_F_PRE","PDN_S_PRE", "PDN_F_ACT", "RD",
"PDN_S_ACT", "PUP_PRE", "PUP_ACT", "SREN", "SREX", "NOP" }; "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; return type_map;
} }
// To identify command type from name // To identify command type from name
static cmds getTypeFromName(const std::string name) static cmds getTypeFromName(const std::string& name)
{ {
std::string* typeStrings = getCommandTypeStrings(); std::string* typeStrings = getCommandTypeStrings();
@ -165,7 +181,7 @@ class MemCommand {
private: private:
MemCommand::cmds type; MemCommand::cmds type;
unsigned bank; unsigned bank;
double timestamp; int64_t timestamp;
}; };
} }
#endif // ifndef MEMCOMMAND_H #endif // ifndef MEMCOMMAND_H

View file

@ -31,10 +31,12 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* *
* Authors: Karthik Chandrasekar * Authors: Karthik Chandrasekar, Sven Goossens
* *
*/ */
#include <stdint.h>
#include "Parametrisable.h" #include "Parametrisable.h"
namespace Data { namespace Data {
@ -44,35 +46,35 @@ class MemTimingSpec : public virtual Parametrisable {
void processParameters(); void processParameters();
double clkMhz; double clkMhz;
unsigned RC; int64_t RC;
unsigned RCD; int64_t RCD;
unsigned CCD; int64_t CCD;
unsigned CCD_S; int64_t CCD_S;
unsigned CCD_L; int64_t CCD_L;
unsigned RRD; int64_t RRD;
unsigned RRD_S; int64_t RRD_S;
unsigned RRD_L; int64_t RRD_L;
unsigned FAW; int64_t FAW;
unsigned TAW; int64_t TAW;
unsigned WTR; int64_t WTR;
unsigned WTR_S; int64_t WTR_S;
unsigned WTR_L; int64_t WTR_L;
unsigned REFI; int64_t REFI;
unsigned RL; int64_t RL;
unsigned RP; int64_t RP;
unsigned RFC; int64_t RFC;
unsigned RAS; int64_t RAS;
unsigned WL; int64_t WL;
unsigned AL; int64_t AL;
unsigned DQSCK; int64_t DQSCK;
unsigned RTP; int64_t RTP;
unsigned WR; int64_t WR;
unsigned XP; int64_t XP;
unsigned XPDLL; int64_t XPDLL;
unsigned XS; int64_t XS;
unsigned XSDLL; int64_t XSDLL;
unsigned CKE; int64_t CKE;
unsigned CKESR; int64_t CKESR;
double clkPeriod; double clkPeriod;
}; };
} }

View file

@ -37,23 +37,24 @@
#include "MemoryPowerModel.h" #include "MemoryPowerModel.h"
#include <cmath> // For pow
#include <stdint.h> #include <stdint.h>
#include <cmath> // For pow
#include <iostream> // fmtflags
using namespace std; using namespace std;
using namespace Data; using namespace Data;
// Calculate energy and average power consumption for the given command trace // Calculate energy and average power consumption for the given command trace
void MemoryPowerModel::power_calc(MemorySpecification memSpec, void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
const CommandAnalysis& counters, const CommandAnalysis& c,
int term) int term)
{ {
MemTimingSpec& t = memSpec.memTimingSpec; const MemTimingSpec& t = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
MemPowerSpec& mps = memSpec.memPowerSpec; const MemPowerSpec& mps = memSpec.memPowerSpec;
energy.act_energy = 0.0; energy.act_energy = 0.0;
energy.pre_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 // 1 DQS and 1 DM pin is associated with every data byte
int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8; int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8;
// Size of one clock period for the data bus. // 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 // 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, ddrPeriod,
power.IO_power, power.IO_power,
dqPlusDqsBits); dqPlusDqsBits);
// Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM // 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, ddrPeriod,
power.WR_ODT_power, power.WR_ODT_power,
dqPlusDqsPlusMaskBits); dqPlusDqsPlusMaskBits);
@ -119,14 +120,14 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
if (memArchSpec.nbrOfRanks > 1) { if (memArchSpec.nbrOfRanks > 1) {
// Termination power consumed in the idle rank during reads on the active // Termination power consumed in the idle rank during reads on the active
// rank by each DQ (data) and DQS (data strobe) pin. // 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, ddrPeriod,
power.TermRD_power, power.TermRD_power,
dqPlusDqsBits); dqPlusDqsBits);
// Termination power consumed in the idle rank during writes on the active // 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. // 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, ddrPeriod,
power.TermWR_power, power.TermWR_power,
dqPlusDqsPlusMaskBits); dqPlusDqsPlusMaskBits);
@ -137,101 +138,101 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
+ energy.read_oterm_energy + energy.write_oterm_energy; + energy.read_oterm_energy + energy.write_oterm_energy;
} }
total_cycles = counters.actcycles + counters.precycles + total_cycles = c.actcycles + c.precycles +
counters.f_act_pdcycles + counters.f_pre_pdcycles + c.f_act_pdcycles + c.f_pre_pdcycles +
counters.s_act_pdcycles + counters.s_pre_pdcycles + counters.sref_cycles c.s_act_pdcycles + c.s_pre_pdcycles + c.sref_cycles
+ counters.sref_ref_act_cycles + counters.sref_ref_pre_cycles + + c.sref_ref_act_cycles + c.sref_ref_pre_cycles +
counters.spup_ref_act_cycles + counters.spup_ref_pre_cycles; c.spup_ref_act_cycles + c.spup_ref_pre_cycles;
EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod); EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
energy.act_energy = vdd0Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd0 - mps.idd3n); energy.act_energy = vdd0Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd0 - mps.idd3n);
energy.pre_energy = vdd0Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n); energy.pre_energy = vdd0Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
energy.read_energy = vdd0Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r - mps.idd3n); energy.read_energy = vdd0Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r - mps.idd3n);
energy.write_energy = vdd0Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w - mps.idd3n); energy.write_energy = vdd0Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w - mps.idd3n);
energy.ref_energy = vdd0Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd5 - mps.idd3n); energy.ref_energy = vdd0Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd5 - mps.idd3n);
energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(counters.precycles, mps.idd2n); energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(c.precycles, mps.idd2n);
energy.act_stdby_energy = vdd0Domain.calcTivEnergy(counters.actcycles, mps.idd3n); energy.act_stdby_energy = vdd0Domain.calcTivEnergy(c.actcycles, mps.idd3n);
// Idle energy in the active standby clock cycles // 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 // 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 // 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 // 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 // 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 // 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 // self-refresh cycles energy including a refresh per self-refresh entry
energy.sref_energy = engy_sref(mps.idd6, mps.idd3n, energy.sref_energy = engy_sref(mps.idd6, mps.idd3n,
mps.idd5, mps.vdd, mps.idd5, mps.vdd,
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles), static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles), static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod); static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
// background energy during active auto-refresh cycles in self-refresh // 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 // 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 // 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 // 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 // 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 // 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 // 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 // similar equations as before to support multiple voltage domains in LPDDR2
// and WIDEIO memories // and WIDEIO memories
if (memArchSpec.twoVoltageDomains) { if (memArchSpec.twoVoltageDomains) {
EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod); EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
energy.act_energy += vdd2Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd02 - mps.idd3n2); energy.act_energy += vdd2Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd02 - mps.idd3n2);
energy.pre_energy += vdd2Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2); energy.pre_energy += vdd2Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
energy.read_energy += vdd2Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2); energy.read_energy += vdd2Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2);
energy.write_energy += vdd2Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2); energy.write_energy += vdd2Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2);
energy.ref_energy += vdd2Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2); energy.ref_energy += vdd2Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2);
energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(counters.precycles, mps.idd2n2); energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(c.precycles, mps.idd2n2);
energy.act_stdby_energy += vdd2Domain.calcTivEnergy(counters.actcycles, mps.idd3n2); energy.act_stdby_energy += vdd2Domain.calcTivEnergy(c.actcycles, mps.idd3n2);
// Idle energy in the active standby clock cycles // 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 // 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 // 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 // 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 // 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 // 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, energy.sref_energy += engy_sref(mps.idd62, mps.idd3n2,
mps.idd52, mps.vdd2, mps.idd52, mps.vdd2,
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles), static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles), static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod); static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
// background energy during active auto-refresh cycles in self-refresh // 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 // 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 // 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 // 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 // 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 // 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 // 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 // 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 components for both ranks (in a dual-rank system)
energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy + energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
energy.write_energy + energy.ref_energy + energy.io_term_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.pre_stdby_energy + energy.sref_energy +
energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_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); + 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); power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
} // MemoryPowerModel::power_calc } // 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; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; 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.precision(0);
cout << "* Trace Details:" << endl; cout << "* Trace Details:" << fixed << endl
cout << "Number of Activates: " << fixed << counters.numberofacts << endl; << endl << "#ACT commands: " << c.numberofacts
cout << "Number of Reads: " << counters.numberofreads << endl; << endl << "#RD + #RDA commands: " << c.numberofreads
cout << "Number of Writes: " << counters.numberofwrites << endl; << endl << "#WR + #WRA commands: " << c.numberofwrites
cout << "Number of Precharges: " << counters.numberofpres << endl; /* #PRE commands (precharge all counts a number of #PRE commands equal to the number of active banks) */
cout << "Number of Refreshes: " << counters.numberofrefs << endl; << endl << "#PRE (+ PREA) commands: " << c.numberofpres
cout << "Number of Active Cycles: " << counters.actcycles << endl; << endl << "#REF commands: " << c.numberofrefs
cout << " Number of Active Idle Cycles: " << counters.idlecycles_act << endl; << endl << "#Active Cycles: " << c.actcycles
cout << " Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl; << endl << " #Active Idle Cycles: " << c.idlecycles_act
cout << " Number of Auto-Refresh Active cycles during Self-Refresh " << << endl << " #Active Power-Up Cycles: " << c.pup_act_cycles
"Power-Up: " << counters.spup_ref_act_cycles << endl; << endl << " #Auto-Refresh Active cycles during Self-Refresh Power-Up: " << c.spup_ref_act_cycles
cout << "Number of Precharged Cycles: " << counters.precycles << endl; << endl << "#Precharged Cycles: " << c.precycles
cout << " Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl; << endl << " #Precharged Idle Cycles: " << c.idlecycles_pre
cout << " Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles << endl << " #Precharged Power-Up Cycles: " << c.pup_pre_cycles
<< endl; << endl << " #Auto-Refresh Precharged cycles during Self-Refresh Power-Up: " << c.spup_ref_pre_cycles
cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh" << endl << " #Self-Refresh Power-Up Cycles: " << c.spup_cycles
<< " Power-Up: " << counters.spup_ref_pre_cycles << endl; << endl << "Total Idle Cycles (Active + Precharged): " << c.idlecycles_act + c.idlecycles_pre
cout << " Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles << endl << "#Power-Downs: " << c.f_act_pdns + c.s_act_pdns + c.f_pre_pdns + c.s_pre_pdns
<< endl; << endl << " #Active Fast-exit Power-Downs: " << c.f_act_pdns
cout << "Total Idle Cycles (Active + Precharged): " << << endl << " #Active Slow-exit Power-Downs: " << c.s_act_pdns
counters.idlecycles_act + counters.idlecycles_pre << endl; << endl << " #Precharged Fast-exit Power-Downs: " << c.f_pre_pdns
cout << "Number of Power-Downs: " << counters.f_act_pdns + << endl << " #Precharged Slow-exit Power-Downs: " << c.s_pre_pdns
counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl; << endl << "#Power-Down Cycles: " << c.f_act_pdcycles + c.s_act_pdcycles + c.f_pre_pdcycles + c.s_pre_pdcycles
cout << " Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns << endl << " #Active Fast-exit Power-Down Cycles: " << c.f_act_pdcycles
<< endl; << endl << " #Active Slow-exit Power-Down Cycles: " << c.s_act_pdcycles
cout << " Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns << endl << " #Auto-Refresh Active cycles during Self-Refresh: " << c.sref_ref_act_cycles
<< endl; << endl << " #Precharged Fast-exit Power-Down Cycles: " << c.f_pre_pdcycles
cout << " Number of Precharged Fast-exit Power-Downs: " << << endl << " #Precharged Slow-exit Power-Down Cycles: " << c.s_pre_pdcycles
counters.f_pre_pdns << endl; << endl << " #Auto-Refresh Precharged cycles during Self-Refresh: " << c.sref_ref_pre_cycles
cout << " Number of Precharged Slow-exit Power-Downs: " << << endl << "#Auto-Refresh Cycles: " << c.numberofrefs * memTimingSpec.RFC
counters.s_pre_pdns << endl; << endl << "#Self-Refreshes: " << c.numberofsrefs
cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles + << endl << "#Self-Refresh Cycles: " << c.sref_cycles
counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl; << endl << "----------------------------------------"
cout << " Number of Active Fast-exit Power-Down Cycles: " << << endl << "Total Trace Length (clock cycles): " << total_cycles
counters.f_act_pdcycles << endl; << endl << "----------------------------------------" << endl;
cout << " Number of Active Slow-exit Power-Down Cycles: " <<
counters.s_act_pdcycles << endl; cout.precision(2);
cout << " Number of Auto-Refresh Active cycles during Self-Refresh: " << cout << endl << "* Trace Power and Energy Estimates:" << endl
counters.sref_ref_act_cycles << endl; << endl << "ACT Cmd Energy: " << energy.act_energy << eUnit
cout << " Number of Precharged Fast-exit Power-Down Cycles: " << << endl << "PRE Cmd Energy: " << energy.pre_energy << eUnit
counters.f_pre_pdcycles << endl; << endl << "RD Cmd Energy: " << energy.read_energy << eUnit
cout << " Number of Precharged Slow-exit Power-Down Cycles: " << << endl << "WR Cmd Energy: " << energy.write_energy << eUnit;
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.precision(2);
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) { 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 // No Termination for LPDDR/2/3 and DDR memories
if (memSpec.memArchSpec.termination) { 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) { if (nRanks > 1 && memSpec.memArchSpec.termination) {
cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy << eUnit
<< " pJ" << endl; << endl << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy << eUnit << endl;
cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy
<< " pJ" << endl;
} }
} }
cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy <<
" pJ" << endl; double nRanksDouble = static_cast<double>(nRanks);
cout << " Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act <<
" pJ" << endl; cout << "ACT Stdby Energy: " << nRanksDouble * energy.act_stdby_energy << eUnit
cout << " Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy << << endl << " Active Idle Energy: " << nRanksDouble * energy.idle_energy_act << eUnit
" pJ" << endl; << endl << " Active Power-Up Energy: " << nRanksDouble * energy.pup_act_energy << eUnit
cout << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh" << endl << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_act_energy << eUnit
<< " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy << << endl << "PRE Stdby Energy: " << nRanksDouble * energy.pre_stdby_energy << eUnit
" pJ" << endl; << endl << " Precharge Idle Energy: " << nRanksDouble * energy.idle_energy_pre << eUnit
cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy << << endl << " Precharged Power-Up Energy: " << nRanksDouble * energy.pup_pre_energy << eUnit
" pJ" << endl; << endl << " Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_pre_energy << eUnit
cout << " Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre << << endl << " Self-Refresh Power-Up Energy: " << nRanksDouble * energy.spup_energy << eUnit
" pJ" << endl; << endl << "Total Idle Energy (Active + Precharged): " << nRanksDouble * (energy.idle_energy_act + energy.idle_energy_pre) << eUnit
cout << " Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy << << 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
" pJ" << endl; << endl << " Fast-Exit Active Power-Down Energy: " << nRanksDouble * energy.f_act_pd_energy << eUnit
cout << " Precharge Stdby Energy during Auto-Refresh cycles " << << endl << " Slow-Exit Active Power-Down Energy: " << nRanksDouble * energy.s_act_pd_energy << eUnit
"in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy << << endl << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_act_energy << eUnit
" pJ" << endl; << endl << " Fast-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.f_pre_pd_energy << eUnit
cout << " Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy << << endl << " Slow-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.s_pre_pd_energy << eUnit
" pJ" << endl; << endl << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy << eUnit
cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks * << endl << "Auto-Refresh Energy: " << energy.ref_energy << eUnit
(energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl; << endl << "Self-Refresh Energy: " << nRanksDouble * energy.sref_energy << eUnit
cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy + << endl << "----------------------------------------"
energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl; << endl << "Total Trace Energy: " << energy.total_energy << eUnit
cout << " Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks * << endl << "Average Power: " << power.average_power << " mW"
energy.f_act_pd_energy << " pJ" << endl; << endl << "----------------------------------------" << endl;
cout << " Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
energy.s_act_pd_energy << " pJ" << endl; cout.flags(flags);
cout << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles " cout.precision(precision);
<< "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;
} // MemoryPowerModel::power_print } // MemoryPowerModel::power_print
// Self-refresh active energy estimation (not including background energy) // 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 // IO and Termination power calculation based on Micron Power Calculators
// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW) // 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; const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
MemPowerSpec& memPowerSpec = memSpec.memPowerSpec; const MemPowerSpec& memPowerSpec = memSpec.memPowerSpec;
power.IO_power = memPowerSpec.ioPower; // in mW power.IO_power = memPowerSpec.ioPower; // in mW
power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW

View file

@ -46,8 +46,8 @@ class MemoryPowerModel {
public: public:
// Calculate energy and average power consumption for the given memory // Calculate energy and average power consumption for the given memory
// command trace // command trace
void power_calc(MemorySpecification memSpec, void power_calc(const MemorySpecification& memSpec,
const CommandAnalysis& counters, const CommandAnalysis& c,
int term); int term);
// Used to calculate self-refresh active energy // Used to calculate self-refresh active energy
@ -145,12 +145,12 @@ class MemoryPowerModel {
}; };
// Print the power and energy // Print the power and energy
void power_print(MemorySpecification memSpec, void power_print(const MemorySpecification& memSpec,
int term, int term,
const CommandAnalysis& counters) const; const CommandAnalysis& c) const;
// To derive IO and Termination Power measures using DRAM specification // 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; Energy energy;
Power power; Power power;

View file

@ -106,7 +106,8 @@ class MemoryType {
return val == LPDDR || return val == LPDDR ||
val == LPDDR2 || val == LPDDR2 ||
val == LPDDR3 || val == LPDDR3 ||
val == WIDEIO_SDR; val == WIDEIO_SDR ||
val == DDR4;
} }
bool isDDRFamily() const bool isDDRFamily() const
@ -132,8 +133,10 @@ class MemoryType {
double getCapacitance() const double getCapacitance() const
{ {
// LPDDR/2/3 and DDR memories only have IO Power (no ODT) // LPDDR1/2 memories only have IO Power (no ODT)
// Conservative estimates based on Micron Mobile LPDDR2 Power Calculator // 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 // LPDDR/2/3 IO Capacitance in mF
if (val == LPDDR) { if (val == LPDDR) {
return 0.0000000045; return 0.0000000045;

View file

@ -42,14 +42,19 @@
using namespace Data; using namespace Data;
using namespace std; using namespace std;
TraceParser::TraceParser(int64_t nbrOfBanks) :
counters(nbrOfBanks)
{
}
Data::MemCommand TraceParser::parseLine(std::string line) Data::MemCommand TraceParser::parseLine(std::string line)
{ {
MemCommand memcmd; MemCommand memcmd(MemCommand::UNINITIALIZED, 0, 0);
istringstream linestream(line); istringstream linestream(line);
string item; string item;
double item_val; int64_t item_val;
unsigned itemnum = 0; unsigned itemnum = 0;
MemCommand::cmds type = MemCommand::NOP; // Initialized to prevent warning
while (getline(linestream, item, ',')) { while (getline(linestream, item, ',')) {
if (itemnum == 0) { if (itemnum == 0) {
@ -62,10 +67,8 @@ Data::MemCommand TraceParser::parseLine(std::string line)
} else if (itemnum == 2) { } else if (itemnum == 2) {
stringstream bank(item); stringstream bank(item);
bank >> item_val; bank >> item_val;
memcmd.setType(type);
memcmd.setBank(static_cast<unsigned>(item_val)); memcmd.setBank(static_cast<unsigned>(item_val));
} }
type = memcmd.getType();
itemnum++; itemnum++;
} }
return memcmd; return memcmd;
@ -90,13 +93,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
cmd_list.push_back(cmdline); cmd_list.push_back(cmdline);
nCommands++; nCommands++;
if (nCommands == window) { if (nCommands == window) {
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); counters.getCommands(memSpec, cmd_list, lastupdate);
nCommands = 0; nCommands = 0;
cmd_list.clear(); cmd_list.clear();
} }
} }
lastupdate = true; lastupdate = true;
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); counters.getCommands(memSpec, cmd_list, lastupdate);
cmd_list.clear(); cmd_list.clear();
pwr_trace.close(); pwr_trace.close();
} else { } else {
@ -106,13 +109,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
cmd_list.push_back(cmdline); cmd_list.push_back(cmdline);
nCommands++; nCommands++;
if (nCommands == window) { if (nCommands == window) {
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); counters.getCommands(memSpec, cmd_list, lastupdate);
nCommands = 0; nCommands = 0;
cmd_list.clear(); cmd_list.clear();
} }
} }
lastupdate = true; lastupdate = true;
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); counters.getCommands(memSpec, cmd_list, lastupdate);
cmd_list.clear(); cmd_list.clear();
} }
counters.clear(); counters.clear();

View file

@ -48,6 +48,7 @@
class TraceParser { class TraceParser {
public: public:
TraceParser(int64_t nbrOfBanks);
// list of parsed commands // list of parsed commands
std::vector<Data::MemCommand> cmd_list; std::vector<Data::MemCommand> cmd_list;

View file

@ -41,9 +41,7 @@
#include <string> #include <string>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <typeinfo>
#define MILLION 1000000
template<typename T> template<typename T>
T fromString(const std::string& s, T fromString(const std::string& s,
@ -54,7 +52,7 @@ throw(std::runtime_error)
T t; T t;
if (!(is >> f >> t)) { if (!(is >> f >> t)) {
throw std::runtime_error("fromString cannot convert " + s); throw std::runtime_error("Cannot convert string");
} }
return t; return t;

View file

@ -52,13 +52,13 @@ libDRAMPower::~libDRAMPower()
void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp) 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); cmdList.push_back(cmd);
} }
void libDRAMPower::updateCounters(bool lastUpdate) void libDRAMPower::updateCounters(bool lastUpdate)
{ {
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmdList, lastUpdate); counters.getCommands(memSpec, cmdList, lastUpdate);
cmdList.clear(); cmdList.clear();
} }
@ -72,6 +72,11 @@ void libDRAMPower::clearState()
counters.clear(); counters.clear();
} }
void libDRAMPower::clearCounters(int64_t timestamp)
{
counters.clearStats(timestamp);
}
const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
{ {
return mpm.energy; return mpm.energy;

View file

@ -56,6 +56,8 @@ class libDRAMPower {
void updateCounters(bool lastUpdate); void updateCounters(bool lastUpdate);
void clearCounters(int64_t timestamp);
void clearState(); void clearState();
void calcEnergy(); void calcEnergy();

View file

@ -79,7 +79,8 @@ int main(int argc, char* argv[])
test.doCommand(MemCommand::RDA,0,210); test.doCommand(MemCommand::RDA,0,210);
test.doCommand(MemCommand::ACT,4,232); test.doCommand(MemCommand::ACT,4,232);
test.doCommand(MemCommand::WRA,4,247); 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 //set bool to true when this is the last update of the counters
test.updateCounters(true); test.updateCounters(true);
@ -106,7 +107,7 @@ int main(int argc, char* argv[])
//test.getEnergy().act_stdby_energy //test.getEnergy().act_stdby_energy
std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl; std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
//total active standby energy for both ranks //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" ; test.getEnergy().act_stdby_energy << "\n" ;
std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl; std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl; std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;

View file

@ -41,6 +41,7 @@
* Ani Udipi * Ani Udipi
* Neha Agarwal * Neha Agarwal
* Omar Naji * Omar Naji
* Matthias Jung
*/ */
/** /**
@ -862,7 +863,7 @@ class DRAMCtrl : public AbstractMemory
*/ */
static bool sortTime(const Data::MemCommand& m1, static bool sortTime(const Data::MemCommand& m1,
const Data::MemCommand& m2) { const Data::MemCommand& m2) {
return m1.getTime() < m2.getTime(); return m1.getTimeInt64() < m2.getTimeInt64();
}; };