**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
```
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Karthik Chandrasekar
+ * Authors: Karthik Chandrasekar, Yonghui Li, Sven Goossens
*
*/
#include "CmdScheduler.h"
#include <algorithm> // For max
+#define MILLION 1000000
+
+
using namespace std;
using namespace Data;
// Read the traces and get the transaction. Each transaction is executed by
// scheduling a number of commands to the memory. Hence, the transactions are
// translated into a sequence of commands which will be used for power analysis.
-void cmdScheduler::transTranslation(MemorySpecification memSpec,
+void cmdScheduler::transTranslation(const MemorySpecification& memSpec,
ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
{
commands.open("commands.trace", ifstream::out);
- MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+ const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
nBanks = memArchSpec.nbrOfBanks;
nColumns = memArchSpec.nbrOfColumns;
burstLength = memArchSpec.burstLength;
} // 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());
}
///////////////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);
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;
// 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()) {
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;
// 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;
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.
///////////////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;
}
}
}
///////////////Execution Transactions///////////////////
- Bs = PhysicalAddress.bankAddr;
+ uint64_t Bs = PhysicalAddress.bankAddr;
transType = transTrace[t].type;
tRWTP = getRWTP(transType, 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;
}
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);
}
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;
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);
/////////////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());
// 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;
// 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) {
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:
} 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)) {
// 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;
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;
}
// The logical address of each transaction is translated into a physical address
// which consists of bank group (for DDR4), bank, row and column addresses.
cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans,
- MemorySpecification memSpec)
+ const MemorySpecification& memSpec)
{
- int DecLogic;
+ int64_t DecLogic;
physicalAddr PhysicalAddr;
DecLogic = Trans.logicalAddress;
// row-bank-column-BI-BC-BGI-BL
- if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) {
- unsigned colBits = static_cast<unsigned>(log2(nColumns));
- unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)
- + ((BGI > 1) ? log2(BGI) : 0));
- unsigned bankMask = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1)
- << bankShift;
- unsigned bankAddr = (DecLogic & bankMask) >>
- static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0));
+ if (BGI > 1 && memSpec.memoryType == MemoryType::DDR4) {
+ uint64_t colBits = uintLog2(nColumns);
+ uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
+ uint64_t bankMask = (nBanks / (BI * nbrOfBankGroups) - 1) << bankShift;
+ uint64_t bankAddr = (DecLogic & bankMask) >> (colBits + ((BGI > 1) ? uintLog2(BGI) : 0));
PhysicalAddr.bankAddr = bankAddr;
- unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength));
- unsigned bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
- unsigned bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
+ uint64_t bankGroupShift = uintLog2(burstLength);
+ uint64_t bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
+ uint64_t bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
PhysicalAddr.bankGroupAddr = bankGroupAddr;
- unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
- ((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0));
- unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
- << colShift;
- unsigned colAddr = (DecLogic & colMask) >>
- static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
+ uint64_t colShift = uintLog2(BC * burstLength) +
+ ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
+ uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
+ uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(static_cast<uint64_t>(BC) * burstLength));
PhysicalAddr.colAddr = colAddr;
} else {
- unsigned colBits = static_cast<unsigned>(log2(nColumns));
- unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0));
- unsigned bankMask = static_cast<unsigned>(nBanks / BI - 1) << bankShift;
- unsigned bankAddr = (DecLogic & bankMask) >> colBits;
+ uint64_t colBits = uintLog2(nColumns);
+ uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0);
+ uint64_t bankMask = (nBanks / BI - 1) << bankShift;
+ uint64_t bankAddr = (DecLogic & bankMask) >> colBits;
PhysicalAddr.bankAddr = bankAddr;
- unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
- ((BI > 1) ? log2(BI) : 0));
- unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
- << colShift;
- unsigned colAddr = (DecLogic & colMask) >>
- static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
+ uint64_t colShift = (uintLog2(BC * burstLength) + ((BI > 1) ? uintLog2(BI) : 0));
+ uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
+ uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(BC * burstLength));
PhysicalAddr.colAddr = colAddr;
PhysicalAddr.bankGroupAddr = 0;
}
- unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks));
- unsigned rowMask = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1)
- << rowShift;
- unsigned rowAddr = (DecLogic & rowMask) >> rowShift;
+ uint64_t rowShift = uintLog2(nColumns * nBanks);
+ uint64_t rowMask = (memSpec.memArchSpec.nbrOfRows - 1) << rowShift;
+ uint64_t rowAddr = (DecLogic & rowMask) >> rowShift;
PhysicalAddr.rowAddr = rowAddr;
return PhysicalAddr;
} // cmdScheduler::memoryMap
+
+uint64_t cmdScheduler::uintLog2(uint64_t in)
+{
+ return static_cast<uint64_t>(log2(in));
+}
\ No newline at end of file
// 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.
// 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.
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,
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.
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;
s_pre_pdns = 0;
numberofsrefs = 0;
- pop = 0;
- init = 0;
- zero = 0;
-
actcycles = 0;
precycles = 0;
f_act_pdcycles = 0;
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
{
cached_cmd.clear();
cmd_list.clear();
- full_cmd_list.clear();
last_states.clear();
bankstate.clear();
}
// issued command timestamp, when the auto-precharge would kick in
void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
- const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate)
+ std::vector<MemCommand>& list, bool lastupdate)
{
- for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) {
- const MemCommand& cmd = *i;
- cmd_list.push_back(cmd);
-
+ for (size_t i = 0; i < list.size(); ++i) {
+ MemCommand& cmd = list[i];
MemCommand::cmds cmdType = cmd.getType();
if (cmdType == MemCommand::ACT) {
activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
} else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
// Remove auto-precharge flag from command
- cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag());
+ cmd.setType(cmd.typeWithoutAutoPrechargeFlag());
// Add the auto precharge to the list of cached_cmds
int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
- cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime)));
+ list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime));
}
}
- pop = 0;
- // Note: the extra pre-cmds at the end of the lists, and the cast to double
- // of the size vector is probably not desirable.
- cmd_list.push_back(MemCommand::PRE);
- cached_cmd.push_back(MemCommand::PRE);
- analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1,
- cached_cmd.size()-1, lastupdate);
- cmd_list.clear();
- cached_cmd.clear();
-} // CommandAnalysis::getCommands
-
-// Checks the auto-precharge cached command list and inserts the explicit
-// precharges with the appropriate timestamp in the original command list
-// (by merging) based on their offset from the issuing command. Calls the
-// evaluate function to analyse this expanded list of commands.
+ sort(list.begin(), list.end(), commandSorter);
-void CommandAnalysis::analyse_commands(const int nbrofBanks,
- Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate)
-{
- full_cmd_list.resize(1, MemCommand::PRE);
- unsigned mCommands = 0;
- unsigned mCached = 0;
- for (unsigned i = 0; i < nCommands + nCached + 1; i++) {
- if (cached_cmd.size() > 1) {
- if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
- full_cmd_list[i].setType(MemCommand::PREA);
- init = 1;
- pop = 1;
- } else {
- init = 1;
- if ((cached_cmd[mCached].getTime() > 0) && (cmd_list.
- at(mCommands).getTime() < cached_cmd[mCached].
- getTime()) && ((cmd_list[mCommands].getTime() > 0) ||
- ((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands].
- getType() != MemCommand::PRE)))) {
- full_cmd_list[i] = cmd_list[mCommands];
- mCommands++;
- } else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands].
- getTime() >= cached_cmd[mCached].getTime())) {
- full_cmd_list[i] = cached_cmd[mCached];
- mCached++;
- } else if (cached_cmd[mCached].getTime() == 0) {
- if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands].
- getTime() == 0) && (cmd_list[mCommands].
- getType() != MemCommand::PRE))) {
- full_cmd_list[i] = cmd_list[mCommands];
- mCommands++;
- }
- } else if (cmd_list[mCommands].getTime() == 0) {
- full_cmd_list[i] = cached_cmd[mCached];
- mCached++;
- }
- }
- } else {
- if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
- full_cmd_list[i].setType(MemCommand::PREA);
- init = 1;
- pop = 1;
- } else {
- init = 1;
- if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list.
- at(mCommands).getTime() == 0) && (cmd_list[mCommands].
- getType() != MemCommand::PRE))) {
- full_cmd_list[i] = cmd_list[mCommands];
- mCommands++;
- }
- }
- }
- full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE);
+ if (lastupdate && list.empty() == false) {
+ // Add cycles at the end of the list
+ int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1;
+ list.push_back(MemCommand(MemCommand::NOP, 0, t));
}
- full_cmd_list.pop_back();
- if (pop == 0) {
- full_cmd_list.pop_back();
- }
- if (lastupdate) {
- full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP);
- full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list
- [full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec,
- full_cmd_list[full_cmd_list.size() - 2].getType()) - 1);
- }
+ evaluate(memSpec, list);
+} // CommandAnalysis::getCommands
- evaluate(memSpec, full_cmd_list, nbrofBanks);
-} // CommandAnalysis::analyse_commands
// To get the time of completion of the issued command
// Derived based on JEDEC specifications
-int CommandAnalysis::timeToCompletion(const MemorySpecification&
+int64_t CommandAnalysis::timeToCompletion(const MemorySpecification&
memSpec, MemCommand::cmds type)
{
- int offset = 0;
+ int64_t offset = 0;
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
if (type == MemCommand::RD) {
- offset = static_cast<int>(memTimingSpec.RL +
+ offset = memTimingSpec.RL +
memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
- memArchSpec.dataRate));
+ memArchSpec.dataRate);
} else if (type == MemCommand::WR) {
- offset = static_cast<int>(memTimingSpec.WL +
+ offset = memTimingSpec.WL +
(memArchSpec.burstLength / memArchSpec.dataRate) +
- memTimingSpec.WR);
+ memTimingSpec.WR;
} else if (type == MemCommand::ACT) {
- offset = static_cast<int>(memTimingSpec.RCD);
+ offset = memTimingSpec.RCD;
} else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
- offset = static_cast<int>(memTimingSpec.RP);
+ offset = memTimingSpec.RP;
}
return offset;
} // CommandAnalysis::timeToCompletion
// 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++;
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++;
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
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);
}
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
// 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,
// 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,
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) {
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,
}
}
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) {
} 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
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);
}
}
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;
// 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;
// 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
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);
};
}
* 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 {
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;
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)
}
// 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;
}
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
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;
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
}
}
- 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();
private:
MemCommand::cmds type;
unsigned bank;
- double timestamp;
+ int64_t timestamp;
};
}
#endif // ifndef MEMCOMMAND_H
* 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 {
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;
};
}
#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;
// 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);
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);
+ 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
// 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);
power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
} // MemoryPowerModel::power_calc
-void MemoryPowerModel::power_print(MemorySpecification memSpec, int term, const CommandAnalysis& counters) const
+void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term, const CommandAnalysis& c) const
{
- MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
- MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+ const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
+ const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+ const uint64_t nRanks = static_cast<uint64_t>(memArchSpec.nbrOfRanks);
+ const char eUnit[] = " pJ";
+ ios_base::fmtflags flags = cout.flags();
+ streamsize precision = cout.precision();
cout.precision(0);
- cout << "* Trace Details:" << endl;
- cout << "Number of Activates: " << fixed << counters.numberofacts << endl;
- cout << "Number of Reads: " << counters.numberofreads << endl;
- cout << "Number of Writes: " << counters.numberofwrites << endl;
- cout << "Number of Precharges: " << counters.numberofpres << endl;
- cout << "Number of Refreshes: " << counters.numberofrefs << endl;
- cout << "Number of Active Cycles: " << counters.actcycles << endl;
- cout << " Number of Active Idle Cycles: " << counters.idlecycles_act << endl;
- cout << " Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl;
- cout << " Number of Auto-Refresh Active cycles during Self-Refresh " <<
- "Power-Up: " << counters.spup_ref_act_cycles << endl;
- cout << "Number of Precharged Cycles: " << counters.precycles << endl;
- cout << " Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl;
- cout << " Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles
- << endl;
- cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh"
- << " Power-Up: " << counters.spup_ref_pre_cycles << endl;
- cout << " Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles
- << endl;
- cout << "Total Idle Cycles (Active + Precharged): " <<
- counters.idlecycles_act + counters.idlecycles_pre << endl;
- cout << "Number of Power-Downs: " << counters.f_act_pdns +
- counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl;
- cout << " Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns
- << endl;
- cout << " Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns
- << endl;
- cout << " Number of Precharged Fast-exit Power-Downs: " <<
- counters.f_pre_pdns << endl;
- cout << " Number of Precharged Slow-exit Power-Downs: " <<
- counters.s_pre_pdns << endl;
- cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles +
- counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl;
- cout << " Number of Active Fast-exit Power-Down Cycles: " <<
- counters.f_act_pdcycles << endl;
- cout << " Number of Active Slow-exit Power-Down Cycles: " <<
- counters.s_act_pdcycles << endl;
- cout << " Number of Auto-Refresh Active cycles during Self-Refresh: " <<
- counters.sref_ref_act_cycles << endl;
- cout << " Number of Precharged Fast-exit Power-Down Cycles: " <<
- counters.f_pre_pdcycles << endl;
- cout << " Number of Precharged Slow-exit Power-Down Cycles: " <<
- counters.s_pre_pdcycles << endl;
- cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh: " <<
- counters.sref_ref_pre_cycles << endl;
- cout << "Number of Auto-Refresh Cycles: " << counters.numberofrefs *
- memTimingSpec.RFC << endl;
- cout << "Number of Self-Refreshes: " << counters.numberofsrefs << endl;
- cout << "Number of Self-Refresh Cycles: " << counters.sref_cycles << endl;
- cout << "----------------------------------------" << endl;
- cout << "Total Trace Length (clock cycles): " << total_cycles << endl;
- cout << "----------------------------------------" << endl;
+ cout << "* Trace Details:" << fixed << endl
+ << endl << "#ACT commands: " << c.numberofacts
+ << endl << "#RD + #RDA commands: " << c.numberofreads
+ << endl << "#WR + #WRA commands: " << c.numberofwrites
+ /* #PRE commands (precharge all counts a number of #PRE commands equal to the number of active banks) */
+ << endl << "#PRE (+ PREA) commands: " << c.numberofpres
+ << endl << "#REF commands: " << c.numberofrefs
+ << endl << "#Active Cycles: " << c.actcycles
+ << endl << " #Active Idle Cycles: " << c.idlecycles_act
+ << endl << " #Active Power-Up Cycles: " << c.pup_act_cycles
+ << endl << " #Auto-Refresh Active cycles during Self-Refresh Power-Up: " << c.spup_ref_act_cycles
+ << endl << "#Precharged Cycles: " << c.precycles
+ << endl << " #Precharged Idle Cycles: " << c.idlecycles_pre
+ << endl << " #Precharged Power-Up Cycles: " << c.pup_pre_cycles
+ << endl << " #Auto-Refresh Precharged cycles during Self-Refresh Power-Up: " << c.spup_ref_pre_cycles
+ << endl << " #Self-Refresh Power-Up Cycles: " << c.spup_cycles
+ << endl << "Total Idle Cycles (Active + Precharged): " << c.idlecycles_act + c.idlecycles_pre
+ << endl << "#Power-Downs: " << c.f_act_pdns + c.s_act_pdns + c.f_pre_pdns + c.s_pre_pdns
+ << endl << " #Active Fast-exit Power-Downs: " << c.f_act_pdns
+ << endl << " #Active Slow-exit Power-Downs: " << c.s_act_pdns
+ << endl << " #Precharged Fast-exit Power-Downs: " << c.f_pre_pdns
+ << endl << " #Precharged Slow-exit Power-Downs: " << c.s_pre_pdns
+ << endl << "#Power-Down Cycles: " << c.f_act_pdcycles + c.s_act_pdcycles + c.f_pre_pdcycles + c.s_pre_pdcycles
+ << endl << " #Active Fast-exit Power-Down Cycles: " << c.f_act_pdcycles
+ << endl << " #Active Slow-exit Power-Down Cycles: " << c.s_act_pdcycles
+ << endl << " #Auto-Refresh Active cycles during Self-Refresh: " << c.sref_ref_act_cycles
+ << endl << " #Precharged Fast-exit Power-Down Cycles: " << c.f_pre_pdcycles
+ << endl << " #Precharged Slow-exit Power-Down Cycles: " << c.s_pre_pdcycles
+ << endl << " #Auto-Refresh Precharged cycles during Self-Refresh: " << c.sref_ref_pre_cycles
+ << endl << "#Auto-Refresh Cycles: " << c.numberofrefs * memTimingSpec.RFC
+ << endl << "#Self-Refreshes: " << c.numberofsrefs
+ << endl << "#Self-Refresh Cycles: " << c.sref_cycles
+ << endl << "----------------------------------------"
+ << endl << "Total Trace Length (clock cycles): " << total_cycles
+ << endl << "----------------------------------------" << endl;
+
cout.precision(2);
+ cout << endl << "* Trace Power and Energy Estimates:" << endl
+ << endl << "ACT Cmd Energy: " << energy.act_energy << eUnit
+ << endl << "PRE Cmd Energy: " << energy.pre_energy << eUnit
+ << endl << "RD Cmd Energy: " << energy.read_energy << eUnit
+ << endl << "WR Cmd Energy: " << energy.write_energy << eUnit;
- cout << "\n* Trace Power and Energy Estimates:" << endl;
- cout << "ACT Cmd Energy: " << energy.act_energy << " pJ" << endl;
- cout << "PRE Cmd Energy: " << energy.pre_energy << " pJ" << endl;
- cout << "RD Cmd Energy: " << energy.read_energy << " pJ" << endl;
- cout << "WR Cmd Energy: " << energy.write_energy << " pJ" << endl;
if (term) {
- cout << "RD I/O Energy: " << energy.read_io_energy << " pJ" << endl;
+ cout << "RD I/O Energy: " << energy.read_io_energy << eUnit << endl;
// No Termination for LPDDR/2/3 and DDR memories
if (memSpec.memArchSpec.termination) {
- cout << "WR Termination Energy: " << energy.write_term_energy << " pJ" << endl;
+ cout << "WR Termination Energy: " << energy.write_term_energy << eUnit << endl;
}
- if ((memArchSpec.nbrOfRanks > 1) && memSpec.memArchSpec.termination) {
- cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy
- << " pJ" << endl;
- cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy
- << " pJ" << endl;
+ if (nRanks > 1 && memSpec.memArchSpec.termination) {
+ cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy << eUnit
+ << endl << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy << eUnit << endl;
}
}
- cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy <<
- " pJ" << endl;
- cout << " Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act <<
- " pJ" << endl;
- cout << " Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy <<
- " pJ" << endl;
- cout << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh"
- << " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy <<
- " pJ" << endl;
- cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy <<
- " pJ" << endl;
- cout << " Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre <<
- " pJ" << endl;
- cout << " Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy <<
- " pJ" << endl;
- cout << " Precharge Stdby Energy during Auto-Refresh cycles " <<
- "in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy <<
- " pJ" << endl;
- cout << " Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy <<
- " pJ" << endl;
- cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks *
- (energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl;
- cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy +
- energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl;
- cout << " Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
- energy.f_act_pd_energy << " pJ" << endl;
- cout << " Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
- energy.s_act_pd_energy << " pJ" << endl;
- cout << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles "
- << "in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_act_energy <<
- " pJ" << endl;
- cout << " Fast-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
- energy.f_pre_pd_energy << " pJ" << endl;
- cout << " Slow-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
- energy.s_pre_pd_energy << " pJ" << endl;
- cout << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh " <<
- "cycles in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_pre_energy <<
- " pJ" << endl;
- cout << "Auto-Refresh Energy: " << energy.ref_energy << " pJ" << endl;
- cout << "Self-Refresh Energy: " << memArchSpec.nbrOfRanks * energy.sref_energy <<
- " pJ" << endl;
- cout << "----------------------------------------" << endl;
- cout << "Total Trace Energy: " << energy.total_energy << " pJ" << endl;
- cout << "Average Power: " << power.average_power << " mW" << endl;
- cout << "----------------------------------------" << endl;
+
+ double nRanksDouble = static_cast<double>(nRanks);
+
+ cout << "ACT Stdby Energy: " << nRanksDouble * energy.act_stdby_energy << eUnit
+ << endl << " Active Idle Energy: " << nRanksDouble * energy.idle_energy_act << eUnit
+ << endl << " Active Power-Up Energy: " << nRanksDouble * energy.pup_act_energy << eUnit
+ << endl << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_act_energy << eUnit
+ << endl << "PRE Stdby Energy: " << nRanksDouble * energy.pre_stdby_energy << eUnit
+ << endl << " Precharge Idle Energy: " << nRanksDouble * energy.idle_energy_pre << eUnit
+ << endl << " Precharged Power-Up Energy: " << nRanksDouble * energy.pup_pre_energy << eUnit
+ << endl << " Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_pre_energy << eUnit
+ << endl << " Self-Refresh Power-Up Energy: " << nRanksDouble * energy.spup_energy << eUnit
+ << endl << "Total Idle Energy (Active + Precharged): " << nRanksDouble * (energy.idle_energy_act + energy.idle_energy_pre) << eUnit
+ << endl << "Total Power-Down Energy: " << nRanksDouble * (energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << eUnit
+ << endl << " Fast-Exit Active Power-Down Energy: " << nRanksDouble * energy.f_act_pd_energy << eUnit
+ << endl << " Slow-Exit Active Power-Down Energy: " << nRanksDouble * energy.s_act_pd_energy << eUnit
+ << endl << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_act_energy << eUnit
+ << endl << " Fast-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.f_pre_pd_energy << eUnit
+ << endl << " Slow-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.s_pre_pd_energy << eUnit
+ << endl << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy << eUnit
+ << endl << "Auto-Refresh Energy: " << energy.ref_energy << eUnit
+ << endl << "Self-Refresh Energy: " << nRanksDouble * energy.sref_energy << eUnit
+ << endl << "----------------------------------------"
+ << endl << "Total Trace Energy: " << energy.total_energy << eUnit
+ << endl << "Average Power: " << power.average_power << " mW"
+ << endl << "----------------------------------------" << endl;
+
+ cout.flags(flags);
+ cout.precision(precision);
} // MemoryPowerModel::power_print
// Self-refresh active energy estimation (not including background energy)
// 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
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,
};
// 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;
return val == LPDDR ||
val == LPDDR2 ||
val == LPDDR3 ||
- val == WIDEIO_SDR;
+ val == WIDEIO_SDR ||
+ val == DDR4;
}
bool isDDRFamily() const
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) {
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) {
} 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;
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 {
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();
class TraceParser {
public:
+ TraceParser(int64_t nbrOfBanks);
// list of parsed commands
std::vector<Data::MemCommand> cmd_list;
#include <string>
#include <sstream>
#include <stdexcept>
-#include <typeinfo>
-#define MILLION 1000000
template<typename T>
T fromString(const std::string& s,
T t;
if (!(is >> f >> t)) {
- throw std::runtime_error("fromString cannot convert " + s);
+ throw std::runtime_error("Cannot convert string");
}
return t;
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();
}
counters.clear();
}
+void libDRAMPower::clearCounters(int64_t timestamp)
+{
+ counters.clearStats(timestamp);
+}
+
const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
{
return mpm.energy;
void updateCounters(bool lastUpdate);
+ void clearCounters(int64_t timestamp);
+
void clearState();
void calcEnergy();
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);
//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;
* Ani Udipi
* Neha Agarwal
* Omar Naji
+ * Matthias Jung
*/
/**
*/
static bool sortTime(const Data::MemCommand& m1,
const Data::MemCommand& m2) {
- return m1.getTime() < m2.getTime();
+ return m1.getTimeInt64() < m2.getTimeInt64();
};