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:
parent
137e244bda
commit
86e9a6ffec
19 changed files with 561 additions and 626 deletions
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
|
||||
class TraceParser {
|
||||
public:
|
||||
TraceParser(int64_t nbrOfBanks);
|
||||
// list of parsed commands
|
||||
std::vector<Data::MemCommand> cmd_list;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -56,6 +56,8 @@ class libDRAMPower {
|
|||
|
||||
void updateCounters(bool lastUpdate);
|
||||
|
||||
void clearCounters(int64_t timestamp);
|
||||
|
||||
void clearState();
|
||||
|
||||
void calcEnergy();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue