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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -106,7 +106,8 @@ class MemoryType {
return val == LPDDR ||
val == LPDDR2 ||
val == LPDDR3 ||
val == WIDEIO_SDR;
val == WIDEIO_SDR ||
val == DDR4;
}
bool isDDRFamily() const
@ -132,9 +133,11 @@ class MemoryType {
double getCapacitance() const
{
// LPDDR/2/3 and DDR memories only have IO Power (no ODT)
// Conservative estimates based on Micron Mobile LPDDR2 Power Calculator
// LPDDR/2/3 IO Capacitance in mF
// LPDDR1/2 memories only have IO Power (no ODT)
// LPDDR3 has optional ODT, but it is typically not used (reflections are elimitated by other means (layout))
// The capacitance values are conservative and based on Micron Mobile LPDDR2 Power Calculator
// LPDDR/2/3 IO Capacitance in mF
if (val == LPDDR) {
return 0.0000000045;
} else if (val == LPDDR2) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -79,7 +79,8 @@ int main(int argc, char* argv[])
test.doCommand(MemCommand::RDA,0,210);
test.doCommand(MemCommand::ACT,4,232);
test.doCommand(MemCommand::WRA,4,247);
test.doCommand(MemCommand::PDN_F_ACT,3,248);
// Need at least tWRAPDEN = AL + CWL + BL/2 + WR + 1 cycles between WR and PDN_F_PRE
test.doCommand(MemCommand::PDN_F_PRE,3,265);
//set bool to true when this is the last update of the counters
test.updateCounters(true);
@ -106,7 +107,7 @@ int main(int argc, char* argv[])
//test.getEnergy().act_stdby_energy
std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
//total active standby energy for both ranks
std::cout << "ACT Std Energy total ranks" << "\t" << memSpec.memArchSpec.nbrOfRanks *
std::cout << "ACT Std Energy total ranks" << "\t" << static_cast<double>(memSpec.memArchSpec.nbrOfRanks) *
test.getEnergy().act_stdby_energy << "\n" ;
std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;

View file

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