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:**
|
**To cite the DRAMPower Tool:**
|
||||||
```
|
```
|
||||||
[1] "DRAMPower: Open-source DRAM power & energy estimation tool"
|
[1] DRAMPower: Open-source DRAM Power & Energy Estimation Tool
|
||||||
Karthik Chandrasekar, Christian Weis, Yonghui Li, Benny Akesson, Norbert Wehn, and Kees Goossens
|
Karthik Chandrasekar, Christian Weis, Yonghui Li, Sven Goossens, Matthias Jung, Omar Naji, Benny Akesson, Norbert Wehn, and Kees Goossens
|
||||||
URL: http://www.drampower.info
|
URL: http://www.drampower.info
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Karthik Chandrasekar
|
* Authors: Karthik Chandrasekar, Yonghui Li, Sven Goossens
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "CmdScheduler.h"
|
#include "CmdScheduler.h"
|
||||||
|
@ -42,17 +42,20 @@
|
||||||
#include <algorithm> // For max
|
#include <algorithm> // For max
|
||||||
|
|
||||||
|
|
||||||
|
#define MILLION 1000000
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
// Read the traces and get the transaction. Each transaction is executed by
|
// Read the traces and get the transaction. Each transaction is executed by
|
||||||
// scheduling a number of commands to the memory. Hence, the transactions are
|
// scheduling a number of commands to the memory. Hence, the transactions are
|
||||||
// translated into a sequence of commands which will be used for power analysis.
|
// translated into a sequence of commands which will be used for power analysis.
|
||||||
void cmdScheduler::transTranslation(MemorySpecification memSpec,
|
void cmdScheduler::transTranslation(const MemorySpecification& memSpec,
|
||||||
ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
|
ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown)
|
||||||
{
|
{
|
||||||
commands.open("commands.trace", ifstream::out);
|
commands.open("commands.trace", ifstream::out);
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
nBanks = memArchSpec.nbrOfBanks;
|
nBanks = memArchSpec.nbrOfBanks;
|
||||||
nColumns = memArchSpec.nbrOfColumns;
|
nColumns = memArchSpec.nbrOfColumns;
|
||||||
burstLength = memArchSpec.burstLength;
|
burstLength = memArchSpec.burstLength;
|
||||||
|
@ -77,13 +80,14 @@ void cmdScheduler::transTranslation(MemorySpecification memSpec,
|
||||||
} // cmdScheduler::transTranslation
|
} // cmdScheduler::transTranslation
|
||||||
|
|
||||||
// initialize the variables and vectors for starting command scheduling.
|
// initialize the variables and vectors for starting command scheduling.
|
||||||
void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
|
void cmdScheduler::schedulingInitialization(const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
|
|
||||||
ACT.resize(2 * memSpec.memArchSpec.nbrOfBanks);
|
const size_t numBanks = static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks);
|
||||||
RDWR.resize(2 * memSpec.memArchSpec.nbrOfBanks);
|
ACT.resize(2 * numBanks);
|
||||||
PRE.resize(memSpec.memArchSpec.nbrOfBanks);
|
RDWR.resize(2 * numBanks);
|
||||||
|
PRE.resize(numBanks);
|
||||||
bankaccess = memSpec.memArchSpec.nbrOfBanks;
|
bankaccess = memSpec.memArchSpec.nbrOfBanks;
|
||||||
if (!ACT.empty()) {
|
if (!ACT.empty()) {
|
||||||
ACT.erase(ACT.begin(), ACT.end());
|
ACT.erase(ACT.begin(), ACT.end());
|
||||||
|
@ -96,14 +100,15 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////initialization//////////////
|
///////////////initialization//////////////
|
||||||
for (unsigned i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
|
for (int64_t i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) {
|
||||||
cmd.Type = PRECHARGE;
|
cmd.Type = PRECHARGE;
|
||||||
cmd.bank = i;
|
cmd.bank = static_cast<unsigned>(i);
|
||||||
cmd.name = "PRE";
|
cmd.name = "PRE";
|
||||||
if (memSpec.id == "WIDEIO_SDR")
|
if (memSpec.id == "WIDEIO_SDR") {
|
||||||
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.TAW);
|
cmd.time = 1 - memSpec.memTimingSpec.TAW;
|
||||||
else
|
} else {
|
||||||
cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.FAW);
|
cmd.time = 1 - memSpec.memTimingSpec.FAW;
|
||||||
|
}
|
||||||
|
|
||||||
PRE.push_back(cmd);
|
PRE.push_back(cmd);
|
||||||
|
|
||||||
|
@ -114,7 +119,7 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
|
||||||
cmd.Type = WRITE;
|
cmd.Type = WRITE;
|
||||||
cmd.name = "WRITE";
|
cmd.name = "WRITE";
|
||||||
cmd.time = -1;
|
cmd.time = -1;
|
||||||
RDWR[i].push_back(cmd);
|
RDWR[static_cast<size_t>(i)].push_back(cmd);
|
||||||
}
|
}
|
||||||
tREF = memTimingSpec.REFI;
|
tREF = memTimingSpec.REFI;
|
||||||
transFinish.time = 0;
|
transFinish.time = 0;
|
||||||
|
@ -130,14 +135,14 @@ void cmdScheduler::schedulingInitialization(MemorySpecification memSpec)
|
||||||
// transactions are generated according to the information read from the traces.
|
// transactions are generated according to the information read from the traces.
|
||||||
// Then the command scheduling function is triggered to generate commands and
|
// Then the command scheduling function is triggered to generate commands and
|
||||||
// schedule them to the memory according to the timing constraints.
|
// schedule them to the memory according to the timing constraints.
|
||||||
void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memSpec)
|
void cmdScheduler::getTrans(std::ifstream& trans_trace, const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
std::string line;
|
std::string line;
|
||||||
|
|
||||||
transTime = 0;
|
transTime = 0;
|
||||||
unsigned newtranstime;
|
uint64_t newtranstime;
|
||||||
unsigned transAddr;
|
uint64_t transAddr;
|
||||||
unsigned transType = 1;
|
int64_t transType = 1;
|
||||||
trans TransItem;
|
trans TransItem;
|
||||||
|
|
||||||
if (!transTrace.empty()) {
|
if (!transTrace.empty()) {
|
||||||
|
@ -147,12 +152,12 @@ void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memS
|
||||||
while (getline(trans_trace, line)) {
|
while (getline(trans_trace, line)) {
|
||||||
istringstream linestream(line);
|
istringstream linestream(line);
|
||||||
string item;
|
string item;
|
||||||
unsigned itemnum = 0;
|
uint64_t itemnum = 0;
|
||||||
while (getline(linestream, item, ',')) {
|
while (getline(linestream, item, ',')) {
|
||||||
if (itemnum == 0) {
|
if (itemnum == 0) {
|
||||||
stringstream timestamp(item);
|
stringstream timestamp(item);
|
||||||
timestamp >> newtranstime;
|
timestamp >> newtranstime;
|
||||||
transTime = transTime + newtranstime;
|
transTime = transTime + static_cast<int64_t>(newtranstime);
|
||||||
} else if (itemnum == 1) {
|
} else if (itemnum == 1) {
|
||||||
if (item == "write" || item == "WRITE") {
|
if (item == "write" || item == "WRITE") {
|
||||||
transType = WRITE;
|
transType = WRITE;
|
||||||
|
@ -191,33 +196,35 @@ void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memS
|
||||||
// be scheduled until all the commands for the current one are scheduled.
|
// be scheduled until all the commands for the current one are scheduled.
|
||||||
// After the scheduling, a sequence of commands are obtained and they are written
|
// After the scheduling, a sequence of commands are obtained and they are written
|
||||||
// into commands.txt which will be used for power analysis.
|
// into commands.txt which will be used for power analysis.
|
||||||
void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
void cmdScheduler::analyticalScheduling(const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
int Bs = -1;
|
int64_t transType = -1;
|
||||||
int transType = -1;
|
int64_t timer = 0;
|
||||||
double timer = 0;
|
uint64_t bankGroupPointer = 0;
|
||||||
int bankGroupPointer = 0;
|
uint64_t bankGroupAddr = 0;
|
||||||
int bankGroupAddr = 0;
|
|
||||||
bool collisionFound;
|
bool collisionFound;
|
||||||
physicalAddr PhysicalAddress;
|
physicalAddr PhysicalAddress;
|
||||||
bool bankGroupSwitch = false;
|
bool bankGroupSwitch = false;
|
||||||
std::vector<unsigned> bankPointer(nbrOfBankGroups, 0);
|
std::vector<uint64_t> bankPointer(static_cast<size_t>(nbrOfBankGroups), 0);
|
||||||
std::vector<int> bankAccessNum(nBanks, -1);
|
std::vector<int64_t> bankAccessNum(static_cast<size_t>(nBanks), -1);
|
||||||
std::vector<bool> ACTSchedule(nBanks, false);
|
std::vector<bool> ACTSchedule(static_cast<size_t>(nBanks), false);
|
||||||
int bankAddr = -1;
|
uint64_t bankAddr = 0;
|
||||||
double endTime = 0;
|
int64_t endTime = 0;
|
||||||
double tComing_REF = 0;
|
int64_t tComing_REF = 0;
|
||||||
|
|
||||||
Inselfrefresh = 0;
|
Inselfrefresh = 0;
|
||||||
|
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
|
|
||||||
for (unsigned t = 0; t < transTrace.size(); t++) {
|
for (uint64_t t = 0; t < transTrace.size(); t++) {
|
||||||
cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
|
cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end());
|
||||||
|
|
||||||
for (unsigned i = 0; i < nBanks; i++) {
|
for (auto a : ACTSchedule) {
|
||||||
ACTSchedule[i] = false;
|
a = false;
|
||||||
bankAccessNum[i] = -1;
|
}
|
||||||
|
|
||||||
|
for (auto& b : bankAccessNum) {
|
||||||
|
b = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
timingsGet = false;
|
timingsGet = false;
|
||||||
|
@ -225,13 +232,13 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
|
|
||||||
PhysicalAddress = memoryMap(transTrace[t], memSpec);
|
PhysicalAddress = memoryMap(transTrace[t], memSpec);
|
||||||
|
|
||||||
for (unsigned i = 0; i < nbrOfBankGroups; i++) {
|
for (auto& b : bankPointer) {
|
||||||
bankPointer[i] = PhysicalAddress.bankAddr; // the bank pointer per group.
|
b = PhysicalAddress.bankAddr; // the bank pointer per group.
|
||||||
}
|
}
|
||||||
bankGroupPointer = PhysicalAddress.bankGroupAddr;
|
bankGroupPointer = PhysicalAddress.bankGroupAddr;
|
||||||
|
|
||||||
endTime = max(transFinish.time, PRE[transFinish.bank].time +
|
endTime = max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time +
|
||||||
static_cast<int>(memTimingSpec.RP));
|
static_cast<int>(memTimingSpec.RP));
|
||||||
|
|
||||||
// Before starting the scheduling for the next transaction, it has to
|
// Before starting the scheduling for the next transaction, it has to
|
||||||
// check whether it is necessary for implementing power down.
|
// check whether it is necessary for implementing power down.
|
||||||
|
@ -244,14 +251,12 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
|
|
||||||
///////////////Scheduling Refresh////////////////////////
|
///////////////Scheduling Refresh////////////////////////
|
||||||
if (((transFinish.time >= tREF) || (timer >= tREF))) {
|
if (((transFinish.time >= tREF) || (timer >= tREF))) {
|
||||||
for (double i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
|
for (int64_t i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) /
|
||||||
memTimingSpec.REFI : 0); i++) {
|
memTimingSpec.REFI : 0); i++) {
|
||||||
cmd.bank = 0;
|
cmd.bank = 0;
|
||||||
cmd.name = "REF";
|
cmd.name = "REF";
|
||||||
cmd.time = max(max(max(transFinish.time, PRE[transFinish.bank].time
|
cmd.time = max(max(max(transFinish.time, PRE[static_cast<size_t>(transFinish.bank)].time + memTimingSpec.RP), tREF), startTime);
|
||||||
+ static_cast<int>(memTimingSpec.RP)), tREF), startTime);
|
if ((power_down == SELF_REFRESH && !Inselfrefresh) || power_down != SELF_REFRESH) {
|
||||||
if (((power_down == SELF_REFRESH) && !Inselfrefresh) ||
|
|
||||||
(power_down != SELF_REFRESH)) {
|
|
||||||
cmdScheduling.push_back(cmd);
|
cmdScheduling.push_back(cmd);
|
||||||
startTime = cmd.time + memTimingSpec.RFC;
|
startTime = cmd.time + memTimingSpec.RFC;
|
||||||
}
|
}
|
||||||
|
@ -262,7 +267,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
///////////////Execution Transactions///////////////////
|
///////////////Execution Transactions///////////////////
|
||||||
Bs = PhysicalAddress.bankAddr;
|
uint64_t Bs = PhysicalAddress.bankAddr;
|
||||||
transType = transTrace[t].type;
|
transType = transTrace[t].type;
|
||||||
|
|
||||||
tRWTP = getRWTP(transType, memSpec);
|
tRWTP = getRWTP(transType, memSpec);
|
||||||
|
@ -280,9 +285,8 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
bankGroupSwitch = true;
|
bankGroupSwitch = true;
|
||||||
}
|
}
|
||||||
// update to the current bank group address.
|
// update to the current bank group address.
|
||||||
bankGroupAddr = PhysicalAddress.bankGroupAddr + j;
|
bankGroupAddr = PhysicalAddress.bankGroupAddr + static_cast<uint64_t>(j);
|
||||||
bankAddr = bankGroupAddr * nBanks / nbrOfBankGroups +
|
bankAddr = bankGroupAddr * static_cast<uint64_t>(nBanks) / nbrOfBankGroups + bankPointer[bankGroupAddr];
|
||||||
bankPointer[bankGroupAddr];
|
|
||||||
} else {
|
} else {
|
||||||
bankAddr = Bs + i;
|
bankAddr = Bs + i;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +316,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
static_cast<int>(memTimingSpec.TAW));
|
static_cast<int>(memTimingSpec.TAW));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((i == 0) && (j == 0)) {
|
if (i == 0 && j == 0) {
|
||||||
cmd.time = max(cmd.time, PreRDWR.time + 1);
|
cmd.time = max(cmd.time, PreRDWR.time + 1);
|
||||||
cmd.time = max(cmd.time, timer);
|
cmd.time = max(cmd.time, timer);
|
||||||
cmd.time = max(startTime, cmd.time);
|
cmd.time = max(startTime, cmd.time);
|
||||||
|
@ -358,7 +362,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
}
|
}
|
||||||
for (int ACTBank = static_cast<int>(ACT.size() - 1);
|
for (int ACTBank = static_cast<int>(ACT.size() - 1);
|
||||||
ACTBank >= 0; ACTBank--) {
|
ACTBank >= 0; ACTBank--) {
|
||||||
if (ACT[ACTBank].bank == bankAddr) {
|
if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
|
||||||
cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
|
cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time
|
||||||
+ static_cast<int>(memTimingSpec.RCD));
|
+ static_cast<int>(memTimingSpec.RCD));
|
||||||
break;
|
break;
|
||||||
|
@ -392,7 +396,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
PRE[bankAddr].name = "PRE";
|
PRE[bankAddr].name = "PRE";
|
||||||
for (int ACTBank = static_cast<int>(ACT.size() - 1);
|
for (int ACTBank = static_cast<int>(ACT.size() - 1);
|
||||||
ACTBank >= 0; ACTBank--) {
|
ACTBank >= 0; ACTBank--) {
|
||||||
if (ACT[ACTBank].bank == bankAddr) {
|
if (ACT[ACTBank].bank == static_cast<int64_t>(bankAddr)) {
|
||||||
PRE[bankAddr].time = max(ACT.back().time +
|
PRE[bankAddr].time = max(ACT.back().time +
|
||||||
static_cast<int>(memTimingSpec.RAS),
|
static_cast<int>(memTimingSpec.RAS),
|
||||||
PreRDWR.time + tRWTP);
|
PreRDWR.time + tRWTP);
|
||||||
|
@ -419,7 +423,7 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
/////////////Update Vector Length/////////////////
|
/////////////Update Vector Length/////////////////
|
||||||
// the vector length is reduced so that less memory is used for running
|
// the vector length is reduced so that less memory is used for running
|
||||||
// this tool.
|
// this tool.
|
||||||
if (ACT.size() >= memSpec.memArchSpec.nbrOfBanks) {
|
if (ACT.size() >= static_cast<size_t>(memSpec.memArchSpec.nbrOfBanks)) {
|
||||||
for (int m = 0; m < BI * BGI; m++) {
|
for (int m = 0; m < BI * BGI; m++) {
|
||||||
ACT.erase(ACT.begin());
|
ACT.erase(ACT.begin());
|
||||||
RDWR[0].erase(RDWR[0].begin(), RDWR[0].end());
|
RDWR[0].erase(RDWR[0].begin(), RDWR[0].end());
|
||||||
|
@ -443,14 +447,14 @@ void cmdScheduler::analyticalScheduling(MemorySpecification memSpec)
|
||||||
// to add the power down/up during the command scheduling for transactions.
|
// to add the power down/up during the command scheduling for transactions.
|
||||||
// It is called when the command scheduling for a transaction is finished, and it
|
// It is called when the command scheduling for a transaction is finished, and it
|
||||||
// is also called if there is a refresh.
|
// is also called if there is a refresh.
|
||||||
void cmdScheduler::pdScheduling(double endTime, double timer,
|
void cmdScheduler::pdScheduling(int64_t endTime, int64_t timer,
|
||||||
MemorySpecification memSpec)
|
const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
double ZERO = 0;
|
int64_t ZERO = 0;
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
|
|
||||||
endTime = max(endTime, startTime);
|
endTime = max(endTime, startTime);
|
||||||
double pdTime = max(ZERO, timer - endTime);
|
int64_t pdTime = max(ZERO, timer - endTime);
|
||||||
|
|
||||||
if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
|
if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) {
|
||||||
cmd.bank = 0;
|
cmd.bank = 0;
|
||||||
|
@ -490,11 +494,11 @@ void cmdScheduler::pdScheduling(double endTime, double timer,
|
||||||
|
|
||||||
// get the time when a precharge occurs after a read/write command is scheduled.
|
// get the time when a precharge occurs after a read/write command is scheduled.
|
||||||
// In addition, it copes with different kind of memories.
|
// In addition, it copes with different kind of memories.
|
||||||
int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
|
int64_t cmdScheduler::getRWTP(int64_t transType, const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
int tRWTP_init = 0;
|
int64_t tRWTP_init = 0;
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
|
|
||||||
if (transType == READ) {
|
if (transType == READ) {
|
||||||
switch (memSpec.memoryType) {
|
switch (memSpec.memoryType) {
|
||||||
|
@ -506,13 +510,13 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
|
||||||
case MemoryType::LPDDR2:
|
case MemoryType::LPDDR2:
|
||||||
case MemoryType::LPDDR3:
|
case MemoryType::LPDDR3:
|
||||||
tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
|
tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate +
|
||||||
max(0, static_cast<int>(memTimingSpec.RTP - 2));
|
max(int64_t(0), memTimingSpec.RTP - 2);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MemoryType::DDR2:
|
case MemoryType::DDR2:
|
||||||
tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
|
tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength /
|
||||||
memArchSpec.dataRate +
|
memArchSpec.dataRate +
|
||||||
max(static_cast<int>(memTimingSpec.RTP), 2) - 2;
|
max(memTimingSpec.RTP, int64_t(2)) - 2;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MemoryType::DDR3:
|
case MemoryType::DDR3:
|
||||||
|
@ -525,10 +529,10 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
|
||||||
} else if (transType == WRITE) {
|
} else if (transType == WRITE) {
|
||||||
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
|
if (memSpec.memoryType == MemoryType::WIDEIO_SDR) {
|
||||||
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
|
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
|
||||||
memArchSpec.dataRate - 1 + memSpec.memTimingSpec.WR;
|
memArchSpec.dataRate - 1 + memTimingSpec.WR;
|
||||||
} else {
|
} else {
|
||||||
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
|
tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength /
|
||||||
memArchSpec.dataRate + memSpec.memTimingSpec.WR;
|
memArchSpec.dataRate + memTimingSpec.WR;
|
||||||
}
|
}
|
||||||
if ((memSpec.memoryType == MemoryType::LPDDR2) ||
|
if ((memSpec.memoryType == MemoryType::LPDDR2) ||
|
||||||
(memSpec.memoryType == MemoryType::LPDDR3)) {
|
(memSpec.memoryType == MemoryType::LPDDR3)) {
|
||||||
|
@ -543,11 +547,11 @@ int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec)
|
||||||
// In particular, tSwitch_init is generally used to provide the timings for
|
// In particular, tSwitch_init is generally used to provide the timings for
|
||||||
// scheduling a read/write command after a read/write command which have been
|
// scheduling a read/write command after a read/write command which have been
|
||||||
// scheduled to any possible banks within any possible bank groups (DDR4).
|
// scheduled to any possible banks within any possible bank groups (DDR4).
|
||||||
void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSpec,
|
void cmdScheduler::getTimingConstraints(bool BGSwitch, const MemorySpecification& memSpec,
|
||||||
int PreType, int CurrentType)
|
int64_t PreType, int64_t CurrentType)
|
||||||
{
|
{
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
|
|
||||||
if (memSpec.memoryType != MemoryType::DDR4) {
|
if (memSpec.memoryType != MemoryType::DDR4) {
|
||||||
tRRD_init = memTimingSpec.RRD;
|
tRRD_init = memTimingSpec.RRD;
|
||||||
|
@ -586,7 +590,7 @@ void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSp
|
||||||
if (PreType == CurrentType) {
|
if (PreType == CurrentType) {
|
||||||
tSwitch_init = tCCD_init;
|
tSwitch_init = tCCD_init;
|
||||||
timingsGet = true;
|
timingsGet = true;
|
||||||
} else if ((PreType == WRITE) && (CurrentType == READ)) {
|
} else if (PreType == WRITE && CurrentType == READ) {
|
||||||
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
|
tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength /
|
||||||
memArchSpec.dataRate + tWTR_init;
|
memArchSpec.dataRate + tWTR_init;
|
||||||
}
|
}
|
||||||
|
@ -601,59 +605,55 @@ void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSp
|
||||||
// The logical address of each transaction is translated into a physical address
|
// The logical address of each transaction is translated into a physical address
|
||||||
// which consists of bank group (for DDR4), bank, row and column addresses.
|
// which consists of bank group (for DDR4), bank, row and column addresses.
|
||||||
cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans,
|
cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans,
|
||||||
MemorySpecification memSpec)
|
const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
int DecLogic;
|
int64_t DecLogic;
|
||||||
physicalAddr PhysicalAddr;
|
physicalAddr PhysicalAddr;
|
||||||
|
|
||||||
DecLogic = Trans.logicalAddress;
|
DecLogic = Trans.logicalAddress;
|
||||||
|
|
||||||
// row-bank-column-BI-BC-BGI-BL
|
// row-bank-column-BI-BC-BGI-BL
|
||||||
if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) {
|
if (BGI > 1 && memSpec.memoryType == MemoryType::DDR4) {
|
||||||
unsigned colBits = static_cast<unsigned>(log2(nColumns));
|
uint64_t colBits = uintLog2(nColumns);
|
||||||
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)
|
uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
|
||||||
+ ((BGI > 1) ? log2(BGI) : 0));
|
uint64_t bankMask = (nBanks / (BI * nbrOfBankGroups) - 1) << bankShift;
|
||||||
unsigned bankMask = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1)
|
uint64_t bankAddr = (DecLogic & bankMask) >> (colBits + ((BGI > 1) ? uintLog2(BGI) : 0));
|
||||||
<< bankShift;
|
|
||||||
unsigned bankAddr = (DecLogic & bankMask) >>
|
|
||||||
static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0));
|
|
||||||
PhysicalAddr.bankAddr = bankAddr;
|
PhysicalAddr.bankAddr = bankAddr;
|
||||||
|
|
||||||
unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength));
|
uint64_t bankGroupShift = uintLog2(burstLength);
|
||||||
unsigned bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
|
uint64_t bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift;
|
||||||
unsigned bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
|
uint64_t bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift;
|
||||||
PhysicalAddr.bankGroupAddr = bankGroupAddr;
|
PhysicalAddr.bankGroupAddr = bankGroupAddr;
|
||||||
|
|
||||||
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
|
uint64_t colShift = uintLog2(BC * burstLength) +
|
||||||
((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0));
|
((BI > 1) ? uintLog2(BI) : 0) + ((BGI > 1) ? uintLog2(BGI) : 0);
|
||||||
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
|
uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
|
||||||
<< colShift;
|
uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(static_cast<uint64_t>(BC) * burstLength));
|
||||||
unsigned colAddr = (DecLogic & colMask) >>
|
|
||||||
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
|
|
||||||
PhysicalAddr.colAddr = colAddr;
|
PhysicalAddr.colAddr = colAddr;
|
||||||
} else {
|
} else {
|
||||||
unsigned colBits = static_cast<unsigned>(log2(nColumns));
|
uint64_t colBits = uintLog2(nColumns);
|
||||||
unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0));
|
uint64_t bankShift = colBits + ((BI > 1) ? uintLog2(BI) : 0);
|
||||||
unsigned bankMask = static_cast<unsigned>(nBanks / BI - 1) << bankShift;
|
uint64_t bankMask = (nBanks / BI - 1) << bankShift;
|
||||||
unsigned bankAddr = (DecLogic & bankMask) >> colBits;
|
uint64_t bankAddr = (DecLogic & bankMask) >> colBits;
|
||||||
PhysicalAddr.bankAddr = bankAddr;
|
PhysicalAddr.bankAddr = bankAddr;
|
||||||
|
|
||||||
unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) +
|
uint64_t colShift = (uintLog2(BC * burstLength) + ((BI > 1) ? uintLog2(BI) : 0));
|
||||||
((BI > 1) ? log2(BI) : 0));
|
uint64_t colMask = (nColumns / (BC * burstLength) - 1) << colShift;
|
||||||
unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1)
|
uint64_t colAddr = (DecLogic & colMask) >> (colShift - uintLog2(BC * burstLength));
|
||||||
<< colShift;
|
|
||||||
unsigned colAddr = (DecLogic & colMask) >>
|
|
||||||
static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength)));
|
|
||||||
PhysicalAddr.colAddr = colAddr;
|
PhysicalAddr.colAddr = colAddr;
|
||||||
|
|
||||||
PhysicalAddr.bankGroupAddr = 0;
|
PhysicalAddr.bankGroupAddr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks));
|
uint64_t rowShift = uintLog2(nColumns * nBanks);
|
||||||
unsigned rowMask = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1)
|
uint64_t rowMask = (memSpec.memArchSpec.nbrOfRows - 1) << rowShift;
|
||||||
<< rowShift;
|
uint64_t rowAddr = (DecLogic & rowMask) >> rowShift;
|
||||||
unsigned rowAddr = (DecLogic & rowMask) >> rowShift;
|
|
||||||
PhysicalAddr.rowAddr = rowAddr;
|
PhysicalAddr.rowAddr = rowAddr;
|
||||||
|
|
||||||
return PhysicalAddr;
|
return PhysicalAddr;
|
||||||
} // cmdScheduler::memoryMap
|
} // cmdScheduler::memoryMap
|
||||||
|
|
||||||
|
uint64_t cmdScheduler::uintLog2(uint64_t in)
|
||||||
|
{
|
||||||
|
return static_cast<uint64_t>(log2(in));
|
||||||
|
}
|
|
@ -59,9 +59,9 @@ class cmdScheduler {
|
||||||
// the format of a transaction.
|
// the format of a transaction.
|
||||||
class trans {
|
class trans {
|
||||||
public:
|
public:
|
||||||
int type;
|
int64_t type;
|
||||||
double timeStamp;
|
int64_t timeStamp;
|
||||||
unsigned logicalAddress;
|
uint64_t logicalAddress;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<trans> transTrace; // to store the transactions.
|
std::vector<trans> transTrace; // to store the transactions.
|
||||||
|
@ -69,18 +69,18 @@ class cmdScheduler {
|
||||||
// the format of physical address.
|
// the format of physical address.
|
||||||
class physicalAddr {
|
class physicalAddr {
|
||||||
public:
|
public:
|
||||||
unsigned rowAddr;
|
uint64_t rowAddr;
|
||||||
unsigned bankAddr;
|
uint64_t bankAddr;
|
||||||
unsigned bankGroupAddr;
|
uint64_t bankGroupAddr;
|
||||||
unsigned colAddr;
|
uint64_t colAddr;
|
||||||
};
|
};
|
||||||
|
|
||||||
// the format of a command.
|
// the format of a command.
|
||||||
class commandItem {
|
class commandItem {
|
||||||
public:
|
public:
|
||||||
int Type;
|
int64_t Type;
|
||||||
int bank;
|
int64_t bank;
|
||||||
double time;
|
int64_t time;
|
||||||
std::string name;
|
std::string name;
|
||||||
physicalAddr PhysicalAddr;
|
physicalAddr PhysicalAddr;
|
||||||
// sorting the commands according to their scheduling time.
|
// sorting the commands according to their scheduling time.
|
||||||
|
@ -107,11 +107,11 @@ class cmdScheduler {
|
||||||
std::vector<commandItem> cmdScheduling;
|
std::vector<commandItem> cmdScheduling;
|
||||||
std::vector<commandItem> cmdList;
|
std::vector<commandItem> cmdList;
|
||||||
unsigned elements;
|
unsigned elements;
|
||||||
int BI, BC, BGI;
|
int64_t BI, BC, BGI;
|
||||||
|
|
||||||
// the function used to translate a transaction into a sequence of
|
// the function used to translate a transaction into a sequence of
|
||||||
// commands which are scheduled to the memory.
|
// commands which are scheduled to the memory.
|
||||||
void transTranslation(Data::MemorySpecification memSpec,
|
void transTranslation(const MemorySpecification& memSpec,
|
||||||
std::ifstream& trans_trace,
|
std::ifstream& trans_trace,
|
||||||
int grouping,
|
int grouping,
|
||||||
int interleaving,
|
int interleaving,
|
||||||
|
@ -119,45 +119,47 @@ class cmdScheduler {
|
||||||
int powerdown);
|
int powerdown);
|
||||||
// get the transactions by reading the traces.
|
// get the transactions by reading the traces.
|
||||||
void getTrans(std::ifstream& pwr_trace,
|
void getTrans(std::ifstream& pwr_trace,
|
||||||
MemorySpecification memSpec);
|
const MemorySpecification& memSpec);
|
||||||
// the initialization function for scheduling.
|
// the initialization function for scheduling.
|
||||||
void schedulingInitialization(MemorySpecification memSpec);
|
void schedulingInitialization(const MemorySpecification& memSpec);
|
||||||
// the function used to schedule commands according to the timing constraints.
|
// the function used to schedule commands according to the timing constraints.
|
||||||
void analyticalScheduling(MemorySpecification memSpec);
|
void analyticalScheduling(const MemorySpecification& memSpec);
|
||||||
// translate the logical address into physical address.
|
// translate the logical address into physical address.
|
||||||
physicalAddr memoryMap(trans Trans,
|
physicalAddr memoryMap(trans Trans,
|
||||||
MemorySpecification memSpec);
|
const MemorySpecification& memSpec);
|
||||||
// the power down and power up are scheduled by pdScheduling
|
// the power down and power up are scheduled by pdScheduling
|
||||||
void pdScheduling(double endTime,
|
void pdScheduling(int64_t endTime,
|
||||||
double timer,
|
int64_t timer,
|
||||||
MemorySpecification memSpec);
|
const MemorySpecification& memSpec);
|
||||||
// get the timings for scheduling a precharge since a read or write command
|
// get the timings for scheduling a precharge since a read or write command
|
||||||
// is scheduled.
|
// is scheduled.
|
||||||
int getRWTP(int transType,
|
int64_t getRWTP(int64_t transType,
|
||||||
MemorySpecification memSpec);
|
const MemorySpecification& memSpec);
|
||||||
// get different kind of timing constraints according to the used memory.
|
// get different kind of timing constraints according to the used memory.
|
||||||
void getTimingConstraints(bool BGSwitch,
|
void getTimingConstraints(bool BGSwitch,
|
||||||
MemorySpecification memSpec,
|
const MemorySpecification& memSpec,
|
||||||
int PreType,
|
int64_t PreType,
|
||||||
int CurrentType);
|
int64_t CurrentType);
|
||||||
|
|
||||||
double transTime;
|
uint64_t uintLog2(uint64_t in);
|
||||||
|
|
||||||
|
int64_t transTime;
|
||||||
// the flag for power down.
|
// the flag for power down.
|
||||||
int power_down;
|
int64_t power_down;
|
||||||
int Inselfrefresh;
|
int64_t Inselfrefresh;
|
||||||
int tRRD_init;
|
int64_t tRRD_init;
|
||||||
int tCCD_init;
|
int64_t tCCD_init;
|
||||||
int tWTR_init;
|
int64_t tWTR_init;
|
||||||
double tREF;
|
int64_t tREF;
|
||||||
double tSwitch_init;
|
int64_t tSwitch_init;
|
||||||
double tRWTP;
|
int64_t tRWTP;
|
||||||
int bankaccess;
|
int64_t bankaccess;
|
||||||
unsigned nBanks;
|
int64_t nBanks;
|
||||||
unsigned nColumns;
|
int64_t nColumns;
|
||||||
unsigned burstLength;
|
int64_t burstLength;
|
||||||
unsigned nbrOfBankGroups;
|
int64_t nbrOfBankGroups;
|
||||||
bool timingsGet;
|
bool timingsGet;
|
||||||
double startTime;
|
int64_t startTime;
|
||||||
|
|
||||||
// the scheduling results for all the transactions are written into
|
// the scheduling results for all the transactions are written into
|
||||||
// commands which will be used by the power analysis part.
|
// commands which will be used by the power analysis part.
|
||||||
|
|
|
@ -45,13 +45,34 @@
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
CommandAnalysis::CommandAnalysis()
|
bool commandSorter(const MemCommand& i, const MemCommand& j)
|
||||||
{
|
{
|
||||||
|
if (i.getTimeInt64() == j.getTimeInt64()) {
|
||||||
|
return i.getType() == MemCommand::PRE && j.getType() != MemCommand::PRE;
|
||||||
|
} else {
|
||||||
|
return i.getTimeInt64() < j.getTimeInt64();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CommandAnalysis::CommandAnalysis(const int nbrofBanks)
|
CommandAnalysis::CommandAnalysis(const int64_t nbrofBanks)
|
||||||
{
|
{
|
||||||
// Initializing all counters and variables
|
// Initializing all counters and variables
|
||||||
|
clearStats(0);
|
||||||
|
zero = 0;
|
||||||
|
|
||||||
|
bankstate.resize(static_cast<size_t>(nbrofBanks), 0);
|
||||||
|
last_states.resize(static_cast<size_t>(nbrofBanks));
|
||||||
|
mem_state = 0;
|
||||||
|
num_active_banks = 0;
|
||||||
|
|
||||||
|
cmd_list.clear();
|
||||||
|
cached_cmd.clear();
|
||||||
|
activation_cycle.resize(static_cast<size_t>(nbrofBanks), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function to clear counters
|
||||||
|
void CommandAnalysis::clearStats(const int64_t timestamp)
|
||||||
|
{
|
||||||
|
|
||||||
numberofacts = 0;
|
numberofacts = 0;
|
||||||
numberofpres = 0;
|
numberofpres = 0;
|
||||||
|
@ -64,10 +85,6 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
|
||||||
s_pre_pdns = 0;
|
s_pre_pdns = 0;
|
||||||
numberofsrefs = 0;
|
numberofsrefs = 0;
|
||||||
|
|
||||||
pop = 0;
|
|
||||||
init = 0;
|
|
||||||
zero = 0;
|
|
||||||
|
|
||||||
actcycles = 0;
|
actcycles = 0;
|
||||||
precycles = 0;
|
precycles = 0;
|
||||||
f_act_pdcycles = 0;
|
f_act_pdcycles = 0;
|
||||||
|
@ -85,28 +102,29 @@ CommandAnalysis::CommandAnalysis(const int nbrofBanks)
|
||||||
idlecycles_act = 0;
|
idlecycles_act = 0;
|
||||||
idlecycles_pre = 0;
|
idlecycles_pre = 0;
|
||||||
|
|
||||||
|
// reset count references to timestamp so that they are moved
|
||||||
|
// to start of next stats generation
|
||||||
|
first_act_cycle = timestamp;
|
||||||
|
last_pre_cycle = timestamp;
|
||||||
|
pdn_cycle = timestamp;
|
||||||
|
sref_cycle = timestamp;
|
||||||
|
end_act_op = timestamp;
|
||||||
|
end_read_op = timestamp;
|
||||||
|
end_write_op = timestamp;
|
||||||
|
|
||||||
latest_act_cycle = -1;
|
latest_act_cycle = -1;
|
||||||
latest_pre_cycle = -1;
|
|
||||||
latest_read_cycle = -1;
|
latest_read_cycle = -1;
|
||||||
latest_write_cycle = -1;
|
latest_write_cycle = -1;
|
||||||
end_read_op = 0;
|
|
||||||
end_write_op = 0;
|
|
||||||
end_act_op = 0;
|
|
||||||
|
|
||||||
first_act_cycle = 0;
|
if (timestamp == 0) {
|
||||||
last_pre_cycle = 0;
|
// set to -1 at beginning of simulation
|
||||||
|
latest_pre_cycle = -1;
|
||||||
bankstate.resize(nbrofBanks, 0);
|
} else {
|
||||||
last_states.resize(nbrofBanks);
|
// NOTE: reference is adjusted by tRP (PRE delay) when updating counter
|
||||||
mem_state = 0;
|
// could remove tRP to ensure counter starts at beginning of next block;
|
||||||
|
// currently simply setting to timestamp for simplicity
|
||||||
sref_cycle = 0;
|
latest_pre_cycle = timestamp;
|
||||||
pdn_cycle = 0;
|
}
|
||||||
|
|
||||||
cmd_list.clear();
|
|
||||||
full_cmd_list.resize(1, MemCommand::PRE);
|
|
||||||
cached_cmd.clear();
|
|
||||||
activation_cycle.resize(nbrofBanks, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// function to clear all arrays
|
// function to clear all arrays
|
||||||
|
@ -114,7 +132,6 @@ void CommandAnalysis::clear()
|
||||||
{
|
{
|
||||||
cached_cmd.clear();
|
cached_cmd.clear();
|
||||||
cmd_list.clear();
|
cmd_list.clear();
|
||||||
full_cmd_list.clear();
|
|
||||||
last_states.clear();
|
last_states.clear();
|
||||||
bankstate.clear();
|
bankstate.clear();
|
||||||
}
|
}
|
||||||
|
@ -125,132 +142,57 @@ void CommandAnalysis::clear()
|
||||||
// issued command timestamp, when the auto-precharge would kick in
|
// issued command timestamp, when the auto-precharge would kick in
|
||||||
|
|
||||||
void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
|
void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
|
||||||
const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate)
|
std::vector<MemCommand>& list, bool lastupdate)
|
||||||
{
|
{
|
||||||
for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) {
|
for (size_t i = 0; i < list.size(); ++i) {
|
||||||
const MemCommand& cmd = *i;
|
MemCommand& cmd = list[i];
|
||||||
cmd_list.push_back(cmd);
|
|
||||||
|
|
||||||
MemCommand::cmds cmdType = cmd.getType();
|
MemCommand::cmds cmdType = cmd.getType();
|
||||||
if (cmdType == MemCommand::ACT) {
|
if (cmdType == MemCommand::ACT) {
|
||||||
activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
|
activation_cycle[cmd.getBank()] = cmd.getTimeInt64();
|
||||||
} else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
|
} else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) {
|
||||||
// Remove auto-precharge flag from command
|
// Remove auto-precharge flag from command
|
||||||
cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag());
|
cmd.setType(cmd.typeWithoutAutoPrechargeFlag());
|
||||||
|
|
||||||
// Add the auto precharge to the list of cached_cmds
|
// Add the auto precharge to the list of cached_cmds
|
||||||
int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
|
int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType),
|
||||||
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
|
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
|
||||||
cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime)));
|
list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pop = 0;
|
sort(list.begin(), list.end(), commandSorter);
|
||||||
// Note: the extra pre-cmds at the end of the lists, and the cast to double
|
|
||||||
// of the size vector is probably not desirable.
|
if (lastupdate && list.empty() == false) {
|
||||||
cmd_list.push_back(MemCommand::PRE);
|
// Add cycles at the end of the list
|
||||||
cached_cmd.push_back(MemCommand::PRE);
|
int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1;
|
||||||
analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1,
|
list.push_back(MemCommand(MemCommand::NOP, 0, t));
|
||||||
cached_cmd.size()-1, lastupdate);
|
}
|
||||||
cmd_list.clear();
|
|
||||||
cached_cmd.clear();
|
evaluate(memSpec, list);
|
||||||
} // CommandAnalysis::getCommands
|
} // CommandAnalysis::getCommands
|
||||||
|
|
||||||
// Checks the auto-precharge cached command list and inserts the explicit
|
|
||||||
// precharges with the appropriate timestamp in the original command list
|
|
||||||
// (by merging) based on their offset from the issuing command. Calls the
|
|
||||||
// evaluate function to analyse this expanded list of commands.
|
|
||||||
|
|
||||||
void CommandAnalysis::analyse_commands(const int nbrofBanks,
|
|
||||||
Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate)
|
|
||||||
{
|
|
||||||
full_cmd_list.resize(1, MemCommand::PRE);
|
|
||||||
unsigned mCommands = 0;
|
|
||||||
unsigned mCached = 0;
|
|
||||||
for (unsigned i = 0; i < nCommands + nCached + 1; i++) {
|
|
||||||
if (cached_cmd.size() > 1) {
|
|
||||||
if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
|
|
||||||
full_cmd_list[i].setType(MemCommand::PREA);
|
|
||||||
init = 1;
|
|
||||||
pop = 1;
|
|
||||||
} else {
|
|
||||||
init = 1;
|
|
||||||
if ((cached_cmd[mCached].getTime() > 0) && (cmd_list.
|
|
||||||
at(mCommands).getTime() < cached_cmd[mCached].
|
|
||||||
getTime()) && ((cmd_list[mCommands].getTime() > 0) ||
|
|
||||||
((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands].
|
|
||||||
getType() != MemCommand::PRE)))) {
|
|
||||||
full_cmd_list[i] = cmd_list[mCommands];
|
|
||||||
mCommands++;
|
|
||||||
} else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands].
|
|
||||||
getTime() >= cached_cmd[mCached].getTime())) {
|
|
||||||
full_cmd_list[i] = cached_cmd[mCached];
|
|
||||||
mCached++;
|
|
||||||
} else if (cached_cmd[mCached].getTime() == 0) {
|
|
||||||
if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands].
|
|
||||||
getTime() == 0) && (cmd_list[mCommands].
|
|
||||||
getType() != MemCommand::PRE))) {
|
|
||||||
full_cmd_list[i] = cmd_list[mCommands];
|
|
||||||
mCommands++;
|
|
||||||
}
|
|
||||||
} else if (cmd_list[mCommands].getTime() == 0) {
|
|
||||||
full_cmd_list[i] = cached_cmd[mCached];
|
|
||||||
mCached++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) {
|
|
||||||
full_cmd_list[i].setType(MemCommand::PREA);
|
|
||||||
init = 1;
|
|
||||||
pop = 1;
|
|
||||||
} else {
|
|
||||||
init = 1;
|
|
||||||
if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list.
|
|
||||||
at(mCommands).getTime() == 0) && (cmd_list[mCommands].
|
|
||||||
getType() != MemCommand::PRE))) {
|
|
||||||
full_cmd_list[i] = cmd_list[mCommands];
|
|
||||||
mCommands++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE);
|
|
||||||
}
|
|
||||||
|
|
||||||
full_cmd_list.pop_back();
|
|
||||||
if (pop == 0) {
|
|
||||||
full_cmd_list.pop_back();
|
|
||||||
}
|
|
||||||
if (lastupdate) {
|
|
||||||
full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP);
|
|
||||||
full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list
|
|
||||||
[full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec,
|
|
||||||
full_cmd_list[full_cmd_list.size() - 2].getType()) - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
evaluate(memSpec, full_cmd_list, nbrofBanks);
|
|
||||||
} // CommandAnalysis::analyse_commands
|
|
||||||
|
|
||||||
// To get the time of completion of the issued command
|
// To get the time of completion of the issued command
|
||||||
// Derived based on JEDEC specifications
|
// Derived based on JEDEC specifications
|
||||||
|
|
||||||
int CommandAnalysis::timeToCompletion(const MemorySpecification&
|
int64_t CommandAnalysis::timeToCompletion(const MemorySpecification&
|
||||||
memSpec, MemCommand::cmds type)
|
memSpec, MemCommand::cmds type)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int64_t offset = 0;
|
||||||
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
|
|
||||||
if (type == MemCommand::RD) {
|
if (type == MemCommand::RD) {
|
||||||
offset = static_cast<int>(memTimingSpec.RL +
|
offset = memTimingSpec.RL +
|
||||||
memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
|
memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
|
||||||
memArchSpec.dataRate));
|
memArchSpec.dataRate);
|
||||||
} else if (type == MemCommand::WR) {
|
} else if (type == MemCommand::WR) {
|
||||||
offset = static_cast<int>(memTimingSpec.WL +
|
offset = memTimingSpec.WL +
|
||||||
(memArchSpec.burstLength / memArchSpec.dataRate) +
|
(memArchSpec.burstLength / memArchSpec.dataRate) +
|
||||||
memTimingSpec.WR);
|
memTimingSpec.WR;
|
||||||
} else if (type == MemCommand::ACT) {
|
} else if (type == MemCommand::ACT) {
|
||||||
offset = static_cast<int>(memTimingSpec.RCD);
|
offset = memTimingSpec.RCD;
|
||||||
} else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
|
} else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
|
||||||
offset = static_cast<int>(memTimingSpec.RP);
|
offset = memTimingSpec.RP;
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
} // CommandAnalysis::timeToCompletion
|
} // CommandAnalysis::timeToCompletion
|
||||||
|
@ -258,38 +200,39 @@ int CommandAnalysis::timeToCompletion(const MemorySpecification&
|
||||||
// Used to analyse a given list of commands and identify command timings
|
// Used to analyse a given list of commands and identify command timings
|
||||||
// and memory state transitions
|
// and memory state transitions
|
||||||
void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
vector<MemCommand>& cmd_list, int nbrofBanks)
|
vector<MemCommand>& cmd_list)
|
||||||
{
|
{
|
||||||
// for each command identify timestamp, type and bank
|
// for each command identify timestamp, type and bank
|
||||||
for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size();
|
for (auto cmd : cmd_list) {
|
||||||
cmd_list_counter++) {
|
|
||||||
// For command type
|
// For command type
|
||||||
int type = cmd_list[cmd_list_counter].getType();
|
int type = cmd.getType();
|
||||||
// For command bank
|
// For command bank
|
||||||
int bank = cmd_list[cmd_list_counter].getBank();
|
int bank = static_cast<int>(cmd.getBank());
|
||||||
// Command Issue timestamp in clock cycles (cc)
|
// Command Issue timestamp in clock cycles (cc)
|
||||||
int64_t timestamp = cmd_list[cmd_list_counter].getTimeInt64();
|
int64_t timestamp = cmd.getTimeInt64();
|
||||||
|
|
||||||
if (type == MemCommand::ACT) {
|
if (type == MemCommand::ACT) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is ACT - update number of acts, bank state of the
|
// If command is ACT - update number of acts, bank state of the
|
||||||
// target bank, first and latest activation cycle and the memory
|
// target bank, first and latest activation cycle and the memory
|
||||||
// state. Update the number of precharged/idle-precharged cycles.
|
// state. Update the number of precharged/idle-precharged cycles.
|
||||||
numberofacts++;
|
numberofacts++;
|
||||||
if (bankstate[bank] == 1) {
|
if (bankstate[static_cast<size_t>(bank)] == 1) {
|
||||||
printWarning("Bank is already active!", type, timestamp, bank);
|
printWarning("Bank is already active!", type, timestamp, bank);
|
||||||
}
|
}
|
||||||
bankstate[bank] = 1;
|
bankstate[static_cast<size_t>(bank)] = 1;
|
||||||
if (mem_state == 0) {
|
if (num_active_banks == 0) {
|
||||||
first_act_cycle = timestamp;
|
first_act_cycle = timestamp;
|
||||||
precycles += max(zero, timestamp - last_pre_cycle);
|
precycles += max(zero, timestamp - last_pre_cycle);
|
||||||
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
||||||
}
|
}
|
||||||
latest_act_cycle = timestamp;
|
latest_act_cycle = timestamp;
|
||||||
mem_state++;
|
num_active_banks++;
|
||||||
} else if (type == MemCommand::RD) {
|
} else if (type == MemCommand::RD) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is RD - update number of reads and read cycle. Check
|
// If command is RD - update number of reads and read cycle. Check
|
||||||
// for active idle cycles (if any).
|
// for active idle cycles (if any).
|
||||||
if (bankstate[bank] == 0) {
|
if (bankstate[static_cast<size_t>(bank)] == 0) {
|
||||||
printWarning("Bank is not active!", type, timestamp, bank);
|
printWarning("Bank is not active!", type, timestamp, bank);
|
||||||
}
|
}
|
||||||
numberofreads++;
|
numberofreads++;
|
||||||
|
@ -297,9 +240,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
latest_act_cycle, timestamp);
|
latest_act_cycle, timestamp);
|
||||||
latest_read_cycle = timestamp;
|
latest_read_cycle = timestamp;
|
||||||
} else if (type == MemCommand::WR) {
|
} else if (type == MemCommand::WR) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is WR - update number of writes and write cycle. Check
|
// If command is WR - update number of writes and write cycle. Check
|
||||||
// for active idle cycles (if any).
|
// for active idle cycles (if any).
|
||||||
if (bankstate[bank] == 0) {
|
if (bankstate[static_cast<size_t>(bank)] == 0) {
|
||||||
printWarning("Bank is not active!", type, timestamp, bank);
|
printWarning("Bank is not active!", type, timestamp, bank);
|
||||||
}
|
}
|
||||||
numberofwrites++;
|
numberofwrites++;
|
||||||
|
@ -307,6 +251,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
latest_act_cycle, timestamp);
|
latest_act_cycle, timestamp);
|
||||||
latest_write_cycle = timestamp;
|
latest_write_cycle = timestamp;
|
||||||
} else if (type == MemCommand::REF) {
|
} else if (type == MemCommand::REF) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is REF - update number of refreshes, set bank state of
|
// If command is REF - update number of refreshes, set bank state of
|
||||||
// all banks to ACT, set the last PRE cycles at RFC-RP cycles from
|
// all banks to ACT, set the last PRE cycles at RFC-RP cycles from
|
||||||
// timestamp, set the number of active cycles to RFC-RP and check
|
// timestamp, set the number of active cycles to RFC-RP and check
|
||||||
|
@ -321,56 +266,54 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
memSpec.memTimingSpec.RP;
|
memSpec.memTimingSpec.RP;
|
||||||
latest_pre_cycle = last_pre_cycle;
|
latest_pre_cycle = last_pre_cycle;
|
||||||
actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
|
actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
|
||||||
mem_state = 0;
|
num_active_banks = 0;
|
||||||
for (int j = 0; j < nbrofBanks; j++) {
|
for (auto& b : bankstate) {
|
||||||
bankstate[j] = 0;
|
b = 0;
|
||||||
}
|
}
|
||||||
} else if (type == MemCommand::PRE) {
|
} else if (type == MemCommand::PRE) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is explicit PRE - update number of precharges, bank
|
// If command is explicit PRE - update number of precharges, bank
|
||||||
// state of the target bank and last and latest precharge cycle.
|
// state of the target bank and last and latest precharge cycle.
|
||||||
// Calculate the number of active cycles if the memory was in the
|
// Calculate the number of active cycles if the memory was in the
|
||||||
// active state before, but there is a state transition to PRE now.
|
// active state before, but there is a state transition to PRE now.
|
||||||
// If not, update the number of precharged cycles and idle cycles.
|
// If not, update the number of precharged cycles and idle cycles.
|
||||||
// Update memory state if needed.
|
// Update memory state if needed.
|
||||||
if (bankstate[bank] == 1) {
|
if (bankstate[static_cast<size_t>(bank)] == 1) {
|
||||||
numberofpres++;
|
numberofpres++;
|
||||||
}
|
}
|
||||||
bankstate[bank] = 0;
|
bankstate[static_cast<size_t>(bank)] = 0;
|
||||||
|
|
||||||
if (mem_state == 1) {
|
if (num_active_banks == 1) {
|
||||||
actcycles += max(zero, timestamp - first_act_cycle);
|
actcycles += max(zero, timestamp - first_act_cycle);
|
||||||
last_pre_cycle = timestamp;
|
last_pre_cycle = timestamp;
|
||||||
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
||||||
latest_act_cycle, timestamp);
|
latest_act_cycle, timestamp);
|
||||||
} else if (mem_state == 0) {
|
} else if (num_active_banks == 0) {
|
||||||
precycles += max(zero, timestamp - last_pre_cycle);
|
precycles += max(zero, timestamp - last_pre_cycle);
|
||||||
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
||||||
last_pre_cycle = timestamp;
|
last_pre_cycle = timestamp;
|
||||||
}
|
}
|
||||||
latest_pre_cycle = timestamp;
|
latest_pre_cycle = timestamp;
|
||||||
if (mem_state > 0) {
|
if (num_active_banks > 0) {
|
||||||
mem_state--;
|
num_active_banks--;
|
||||||
} else {
|
} else {
|
||||||
mem_state = 0;
|
num_active_banks = 0;
|
||||||
}
|
}
|
||||||
} else if (type == MemCommand::PREA) {
|
} else if (type == MemCommand::PREA) {
|
||||||
|
printWarningIfPoweredDown("Command issued while in power-down mode.", type, timestamp, bank);
|
||||||
// If command is explicit PREA (precharge all banks) - update
|
// If command is explicit PREA (precharge all banks) - update
|
||||||
// number of precharges by the number of banks, update the bank
|
// number of precharges by the number of banks, update the bank
|
||||||
// state of all banks to PRE and set the precharge cycle.
|
// state of all banks to PRE and set the precharge cycle.
|
||||||
// Calculate the number of active cycles if the memory was in the
|
// Calculate the number of active cycles if the memory was in the
|
||||||
// active state before, but there is a state transition to PRE now.
|
// active state before, but there is a state transition to PRE now.
|
||||||
// If not, update the number of precharged cycles and idle cycles.
|
// If not, update the number of precharged cycles and idle cycles.
|
||||||
if (timestamp == 0) {
|
numberofpres += num_active_banks;
|
||||||
numberofpres += 0;
|
|
||||||
} else {
|
|
||||||
numberofpres += mem_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mem_state > 0) {
|
if (num_active_banks > 0) {
|
||||||
actcycles += max(zero, timestamp - first_act_cycle);
|
actcycles += max(zero, timestamp - first_act_cycle);
|
||||||
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
||||||
latest_act_cycle, timestamp);
|
latest_act_cycle, timestamp);
|
||||||
} else if (mem_state == 0) {
|
} else if (num_active_banks == 0) {
|
||||||
precycles += max(zero, timestamp - last_pre_cycle);
|
precycles += max(zero, timestamp - last_pre_cycle);
|
||||||
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
||||||
}
|
}
|
||||||
|
@ -378,10 +321,10 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
latest_pre_cycle = timestamp;
|
latest_pre_cycle = timestamp;
|
||||||
last_pre_cycle = timestamp;
|
last_pre_cycle = timestamp;
|
||||||
|
|
||||||
mem_state = 0;
|
num_active_banks = 0;
|
||||||
|
|
||||||
for (int j = 0; j < nbrofBanks; j++) {
|
for (auto& b : bankstate) {
|
||||||
bankstate[j] = 0;
|
b = 0;
|
||||||
}
|
}
|
||||||
} else if (type == MemCommand::PDN_F_ACT) {
|
} else if (type == MemCommand::PDN_F_ACT) {
|
||||||
// If command is fast-exit active power-down - update number of
|
// If command is fast-exit active power-down - update number of
|
||||||
|
@ -391,9 +334,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
// after powering-up. Update active and active idle cycles.
|
// after powering-up. Update active and active idle cycles.
|
||||||
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
|
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
|
||||||
f_act_pdns++;
|
f_act_pdns++;
|
||||||
for (int j = 0; j < nbrofBanks; j++) {
|
last_states = bankstate;
|
||||||
last_states[j] = bankstate[j];
|
|
||||||
}
|
|
||||||
pdn_cycle = timestamp;
|
pdn_cycle = timestamp;
|
||||||
actcycles += max(zero, timestamp - first_act_cycle);
|
actcycles += max(zero, timestamp - first_act_cycle);
|
||||||
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
||||||
|
@ -407,9 +348,7 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
// after powering-up. Update active and active idle cycles.
|
// after powering-up. Update active and active idle cycles.
|
||||||
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
|
printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", type, timestamp, bank);
|
||||||
s_act_pdns++;
|
s_act_pdns++;
|
||||||
for (int j = 0; j < nbrofBanks; j++) {
|
last_states = bankstate;
|
||||||
last_states[j] = bankstate[j];
|
|
||||||
}
|
|
||||||
pdn_cycle = timestamp;
|
pdn_cycle = timestamp;
|
||||||
actcycles += max(zero, timestamp - first_act_cycle);
|
actcycles += max(zero, timestamp - first_act_cycle);
|
||||||
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
||||||
|
@ -461,14 +400,14 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
memSpec.memTimingSpec.XPDLL -
|
memSpec.memTimingSpec.XPDLL -
|
||||||
(2 * memSpec.memTimingSpec.RCD));
|
(2 * memSpec.memTimingSpec.RCD));
|
||||||
}
|
}
|
||||||
} else if ((mem_state != CommandAnalysis::MS_PDN_S_ACT) || (mem_state !=
|
} else if (mem_state != CommandAnalysis::MS_PDN_S_ACT || mem_state != CommandAnalysis::MS_PDN_F_ACT) {
|
||||||
CommandAnalysis::MS_PDN_F_ACT)) {
|
|
||||||
cerr << "Incorrect use of Active Power-Up!" << endl;
|
cerr << "Incorrect use of Active Power-Up!" << endl;
|
||||||
}
|
}
|
||||||
|
num_active_banks = 0;
|
||||||
mem_state = 0;
|
mem_state = 0;
|
||||||
for (int j = 0; j < nbrofBanks; j++) {
|
bankstate = last_states;
|
||||||
bankstate[j] = last_states[j];
|
for (auto& a : last_states) {
|
||||||
mem_state += last_states[j];
|
num_active_banks += static_cast<unsigned int>(a);
|
||||||
}
|
}
|
||||||
first_act_cycle = timestamp;
|
first_act_cycle = timestamp;
|
||||||
} else if (type == MemCommand::PUP_PRE) {
|
} else if (type == MemCommand::PUP_PRE) {
|
||||||
|
@ -493,11 +432,11 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
|
memSpec.memTimingSpec.XPDLL - memSpec.memTimingSpec.RCD -
|
||||||
memSpec.memTimingSpec.RP);
|
memSpec.memTimingSpec.RP);
|
||||||
}
|
}
|
||||||
} else if ((mem_state != CommandAnalysis::MS_PDN_S_PRE) || (mem_state !=
|
} else if (mem_state != CommandAnalysis::MS_PDN_S_PRE || mem_state != CommandAnalysis::MS_PDN_F_PRE) {
|
||||||
CommandAnalysis::MS_PDN_F_PRE)) {
|
|
||||||
cerr << "Incorrect use of Precharged Power-Up!" << endl;
|
cerr << "Incorrect use of Precharged Power-Up!" << endl;
|
||||||
}
|
}
|
||||||
mem_state = 0;
|
mem_state = 0;
|
||||||
|
num_active_banks = 0;
|
||||||
last_pre_cycle = timestamp;
|
last_pre_cycle = timestamp;
|
||||||
} else if (type == MemCommand::SREN) {
|
} else if (type == MemCommand::SREN) {
|
||||||
// If command is self-refresh - update number of self-refreshes,
|
// If command is self-refresh - update number of self-refreshes,
|
||||||
|
@ -583,14 +522,15 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mem_state = 0;
|
mem_state = 0;
|
||||||
} else if ((type == MemCommand::END) || (type == MemCommand::NOP)) {
|
num_active_banks = 0;
|
||||||
|
} else if (type == MemCommand::END || type == MemCommand::NOP) {
|
||||||
// May be optionally used at the end of memory trace for better accuracy
|
// May be optionally used at the end of memory trace for better accuracy
|
||||||
// Update all counters based on completion of operations.
|
// Update all counters based on completion of operations.
|
||||||
if ((mem_state > 0) && (mem_state < 9)) {
|
if (num_active_banks > 0 && mem_state == 0) {
|
||||||
actcycles += max(zero, timestamp - first_act_cycle);
|
actcycles += max(zero, timestamp - first_act_cycle);
|
||||||
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
|
||||||
latest_act_cycle, timestamp);
|
latest_act_cycle, timestamp);
|
||||||
} else if (mem_state == 0) {
|
} else if (num_active_banks == 0 && mem_state == 0) {
|
||||||
precycles += max(zero, timestamp - last_pre_cycle);
|
precycles += max(zero, timestamp - last_pre_cycle);
|
||||||
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
idle_pre_update(memSpec, timestamp, latest_pre_cycle);
|
||||||
} else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
|
} else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
|
||||||
|
@ -604,6 +544,9 @@ void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
|
||||||
} else if (mem_state == CommandAnalysis::MS_SREF) {
|
} else if (mem_state == CommandAnalysis::MS_SREF) {
|
||||||
sref_cycles += max(zero, timestamp - sref_cycle);
|
sref_cycles += max(zero, timestamp - sref_cycle);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
printWarning("Unknown command given, exiting.", type, timestamp, bank);
|
||||||
|
exit(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // CommandAnalysis::evaluate
|
} // CommandAnalysis::evaluate
|
||||||
|
@ -646,14 +589,21 @@ void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
|
||||||
|
|
||||||
void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
|
void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
|
||||||
{
|
{
|
||||||
if (mem_state != 0) {
|
if (num_active_banks != 0) {
|
||||||
printWarning(warning, type, timestamp, bank);
|
printWarning(warning, type, timestamp, bank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
|
void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
|
||||||
{
|
{
|
||||||
if (mem_state == 0) {
|
if (num_active_banks == 0) {
|
||||||
|
printWarning(warning, type, timestamp, bank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandAnalysis::printWarningIfPoweredDown(const string& warning, int type, int64_t timestamp, int bank)
|
||||||
|
{
|
||||||
|
if (mem_state != 0) {
|
||||||
printWarning(warning, type, timestamp, bank);
|
printWarning(warning, type, timestamp, bank);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,10 +58,8 @@ class CommandAnalysis {
|
||||||
MS_PDN_S_PRE = 13, MS_SREF = 14
|
MS_PDN_S_PRE = 13, MS_SREF = 14
|
||||||
};
|
};
|
||||||
|
|
||||||
CommandAnalysis();
|
|
||||||
|
|
||||||
// Returns number of reads, writes, acts, pres and refs in the trace
|
// Returns number of reads, writes, acts, pres and refs in the trace
|
||||||
CommandAnalysis(const int nbrofBanks);
|
CommandAnalysis(const int64_t nbrofBanks);
|
||||||
|
|
||||||
// Number of activate commands
|
// Number of activate commands
|
||||||
int64_t numberofacts;
|
int64_t numberofacts;
|
||||||
|
@ -117,29 +115,25 @@ class CommandAnalysis {
|
||||||
// Number of precharged auto-refresh cycles during self-refresh exit
|
// Number of precharged auto-refresh cycles during self-refresh exit
|
||||||
int64_t spup_ref_pre_cycles;
|
int64_t spup_ref_pre_cycles;
|
||||||
|
|
||||||
|
// function for clearing counters
|
||||||
|
void clearStats(const int64_t timestamp);
|
||||||
|
|
||||||
// function for clearing arrays
|
// function for clearing arrays
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
// To identify auto-precharges
|
// To identify auto-precharges
|
||||||
void getCommands(const MemorySpecification& memSpec,
|
void getCommands(const MemorySpecification& memSpec,
|
||||||
const int
|
|
||||||
nbrofBanks,
|
|
||||||
std::vector<MemCommand>& list,
|
std::vector<MemCommand>& list,
|
||||||
bool lastupdate);
|
bool lastupdate);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned init;
|
|
||||||
int64_t zero;
|
int64_t zero;
|
||||||
unsigned pop;
|
|
||||||
// Cached last read command from the file
|
// Cached last read command from the file
|
||||||
std::vector<MemCommand> cached_cmd;
|
std::vector<MemCommand> cached_cmd;
|
||||||
|
|
||||||
// Stores the memory commands for analysis
|
// Stores the memory commands for analysis
|
||||||
std::vector<MemCommand> cmd_list;
|
std::vector<MemCommand> cmd_list;
|
||||||
|
|
||||||
// Stores all memory commands for analysis
|
|
||||||
std::vector<MemCommand> full_cmd_list;
|
|
||||||
|
|
||||||
// To save states of the different banks, before entering active
|
// To save states of the different banks, before entering active
|
||||||
// power-down mode (slow/fast-exit).
|
// power-down mode (slow/fast-exit).
|
||||||
std::vector<int> last_states;
|
std::vector<int> last_states;
|
||||||
|
@ -171,26 +165,20 @@ class CommandAnalysis {
|
||||||
|
|
||||||
// Memory State
|
// Memory State
|
||||||
unsigned mem_state;
|
unsigned mem_state;
|
||||||
|
unsigned num_active_banks;
|
||||||
|
|
||||||
// Clock cycle of first activate command when memory state changes to ACT
|
// Clock cycle of first activate command when memory state changes to ACT
|
||||||
int64_t first_act_cycle;
|
int64_t first_act_cycle;
|
||||||
|
|
||||||
// Clock cycle of last precharge command when memory state changes to PRE
|
// Clock cycle of last precharge command when memory state changes to PRE
|
||||||
int64_t last_pre_cycle;
|
int64_t last_pre_cycle;
|
||||||
// To collect and analyse all commands including auto-precharges
|
|
||||||
void analyse_commands(const int nbrofBanks,
|
|
||||||
Data::MemorySpecification
|
|
||||||
memSpec,
|
|
||||||
int64_t nCommands,
|
|
||||||
int64_t nCached,
|
|
||||||
bool lastupdate);
|
|
||||||
// To perform timing analysis of a given set of commands and update command counters
|
// To perform timing analysis of a given set of commands and update command counters
|
||||||
void evaluate(const MemorySpecification& memSpec,
|
void evaluate(const MemorySpecification& memSpec,
|
||||||
std::vector<MemCommand>& cmd_list,
|
std::vector<MemCommand>& cmd_list);
|
||||||
int nbrofBanks);
|
|
||||||
|
|
||||||
// To calculate time of completion of any issued command
|
// To calculate time of completion of any issued command
|
||||||
int timeToCompletion(const MemorySpecification& memSpec,
|
int64_t timeToCompletion(const MemorySpecification& memSpec,
|
||||||
MemCommand::cmds type);
|
MemCommand::cmds type);
|
||||||
|
|
||||||
// To update idle period information whenever active cycles may be idle
|
// To update idle period information whenever active cycles may be idle
|
||||||
|
@ -207,6 +195,7 @@ class CommandAnalysis {
|
||||||
|
|
||||||
void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, int bank);
|
void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, int bank);
|
||||||
void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, int bank);
|
void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, int bank);
|
||||||
|
void printWarningIfPoweredDown(const std::string& warning, int type, int64_t timestamp, int bank);
|
||||||
void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
|
void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,13 +31,15 @@
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Karthik Chandrasekar
|
* Authors: Karthik Chandrasekar, Sven Goossens
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H
|
#ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H
|
||||||
#define TOOLS_MEM_ARCHITECTURE_SPEC_H
|
#define TOOLS_MEM_ARCHITECTURE_SPEC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "Parametrisable.h"
|
#include "Parametrisable.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -46,14 +48,14 @@ class MemArchitectureSpec : public virtual Parametrisable {
|
||||||
MemArchitectureSpec();
|
MemArchitectureSpec();
|
||||||
void processParameters();
|
void processParameters();
|
||||||
|
|
||||||
unsigned int burstLength;
|
int64_t burstLength;
|
||||||
unsigned nbrOfBanks;
|
int64_t nbrOfBanks;
|
||||||
unsigned nbrOfRanks;
|
int64_t nbrOfRanks;
|
||||||
unsigned dataRate;
|
int64_t dataRate;
|
||||||
unsigned nbrOfColumns;
|
int64_t nbrOfColumns;
|
||||||
unsigned nbrOfRows;
|
int64_t nbrOfRows;
|
||||||
unsigned width;
|
int64_t width;
|
||||||
unsigned nbrOfBankGroups;
|
int64_t nbrOfBankGroups;
|
||||||
bool dll;
|
bool dll;
|
||||||
bool twoVoltageDomains;
|
bool twoVoltageDomains;
|
||||||
bool termination;
|
bool termination;
|
||||||
|
|
|
@ -44,15 +44,9 @@
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
MemCommand::MemCommand() :
|
|
||||||
type(MemCommand::PRE),
|
|
||||||
bank(0),
|
|
||||||
timestamp(0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
MemCommand::MemCommand(MemCommand::cmds type,
|
MemCommand::MemCommand(MemCommand::cmds type,
|
||||||
unsigned bank, double timestamp) :
|
unsigned bank, int64_t timestamp) :
|
||||||
type(type),
|
type(type),
|
||||||
bank(bank),
|
bank(bank),
|
||||||
timestamp(timestamp)
|
timestamp(timestamp)
|
||||||
|
@ -80,35 +74,35 @@ unsigned MemCommand::getBank() const
|
||||||
}
|
}
|
||||||
|
|
||||||
// For auto-precharge with read or write - to calculate cycle of precharge
|
// For auto-precharge with read or write - to calculate cycle of precharge
|
||||||
int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
|
int64_t MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
|
||||||
MemCommand::cmds type) const
|
MemCommand::cmds type) const
|
||||||
{
|
{
|
||||||
int precharge_offset = 0;
|
int64_t precharge_offset = 0;
|
||||||
|
|
||||||
int BL(static_cast<int>(memSpec.memArchSpec.burstLength));
|
int64_t BL = memSpec.memArchSpec.burstLength;
|
||||||
int RTP(static_cast<int>(memSpec.memTimingSpec.RTP));
|
int64_t RTP = memSpec.memTimingSpec.RTP;
|
||||||
int dataRate(static_cast<int>(memSpec.memArchSpec.dataRate));
|
int64_t dataRate = memSpec.memArchSpec.dataRate;
|
||||||
int AL(static_cast<int>(memSpec.memTimingSpec.AL));
|
int64_t AL = memSpec.memTimingSpec.AL;
|
||||||
int WL(static_cast<int>(memSpec.memTimingSpec.WL));
|
int64_t WL = memSpec.memTimingSpec.WL;
|
||||||
int WR(static_cast<int>(memSpec.memTimingSpec.WR));
|
int64_t WR = memSpec.memTimingSpec.WR;
|
||||||
int B = BL/dataRate;
|
int64_t B = BL/dataRate;
|
||||||
|
|
||||||
const MemoryType::MemoryType_t& memType = memSpec.memoryType;
|
const MemoryType::MemoryType_t& memType = memSpec.memoryType;
|
||||||
|
|
||||||
// Read with auto-precharge
|
// Read with auto-precharge
|
||||||
if (type == MemCommand::RDA) {
|
if (type == MemCommand::RDA) {
|
||||||
if (memType == MemoryType::DDR2) {
|
if (memType == MemoryType::DDR2) {
|
||||||
precharge_offset = B + AL - 2 + max(RTP, 2);
|
precharge_offset = B + AL - 2 + max(RTP, int64_t(2));
|
||||||
} else if (memType == MemoryType::DDR3) {
|
} else if (memType == MemoryType::DDR3) {
|
||||||
precharge_offset = AL + max(RTP, 4);
|
precharge_offset = AL + max(RTP, int64_t(4));
|
||||||
} else if (memType == MemoryType::DDR4) {
|
} else if (memType == MemoryType::DDR4) {
|
||||||
precharge_offset = AL + RTP;
|
precharge_offset = AL + RTP;
|
||||||
} else if (memType == MemoryType::LPDDR) {
|
} else if (memType == MemoryType::LPDDR) {
|
||||||
precharge_offset = B;
|
precharge_offset = B;
|
||||||
} else if (memType == MemoryType::LPDDR2) {
|
} else if (memType == MemoryType::LPDDR2) {
|
||||||
precharge_offset = B + max(0, RTP - 2);
|
precharge_offset = B + max(int64_t(0), RTP - 2);
|
||||||
} else if (memType == MemoryType::LPDDR3) {
|
} else if (memType == MemoryType::LPDDR3) {
|
||||||
precharge_offset = B + max(0, RTP - 4);
|
precharge_offset = B + max(int64_t(0), RTP - 4);
|
||||||
} else if (memType == MemoryType::WIDEIO_SDR) {
|
} else if (memType == MemoryType::WIDEIO_SDR) {
|
||||||
precharge_offset = B;
|
precharge_offset = B;
|
||||||
}
|
}
|
||||||
|
@ -133,19 +127,14 @@ int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec,
|
||||||
return precharge_offset;
|
return precharge_offset;
|
||||||
} // MemCommand::getPrechargeOffset
|
} // MemCommand::getPrechargeOffset
|
||||||
|
|
||||||
void MemCommand::setTime(double _timestamp)
|
void MemCommand::setTime(int64_t _timestamp)
|
||||||
{
|
{
|
||||||
timestamp = _timestamp;
|
timestamp = _timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
double MemCommand::getTime() const
|
|
||||||
{
|
|
||||||
return timestamp;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t MemCommand::getTimeInt64() const
|
int64_t MemCommand::getTimeInt64() const
|
||||||
{
|
{
|
||||||
return static_cast<int64_t>(timestamp);
|
return timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const
|
MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const
|
||||||
|
|
|
@ -86,17 +86,18 @@ class MemCommand {
|
||||||
PUP_ACT = 14,
|
PUP_ACT = 14,
|
||||||
SREN = 15,
|
SREN = 15,
|
||||||
SREX = 16,
|
SREX = 16,
|
||||||
NOP = 17
|
NOP = 17,
|
||||||
|
UNINITIALIZED = 18
|
||||||
};
|
};
|
||||||
|
|
||||||
MemCommand();
|
// MemCommand();
|
||||||
MemCommand(
|
MemCommand(
|
||||||
// Command Type
|
// Command Type
|
||||||
MemCommand::cmds type,
|
MemCommand::cmds type = UNINITIALIZED,
|
||||||
// Target Bank
|
// Target Bank
|
||||||
unsigned bank = 0,
|
unsigned bank = 0,
|
||||||
// Command Issue Timestamp (in cc)
|
// Command Issue Timestamp (in cc)
|
||||||
double timestamp = 0);
|
int64_t timestamp = 0L);
|
||||||
|
|
||||||
// Get command type
|
// Get command type
|
||||||
cmds getType() const;
|
cmds getType() const;
|
||||||
|
@ -111,16 +112,15 @@ class MemCommand {
|
||||||
unsigned getBank() const;
|
unsigned getBank() const;
|
||||||
|
|
||||||
// Set timestamp
|
// Set timestamp
|
||||||
void setTime(double _timestamp);
|
void setTime(int64_t _timestamp);
|
||||||
|
|
||||||
// Get timestamp
|
// Get timestamp
|
||||||
double getTime() const;
|
|
||||||
int64_t getTimeInt64() const;
|
int64_t getTimeInt64() const;
|
||||||
|
|
||||||
cmds typeWithoutAutoPrechargeFlag() const;
|
cmds typeWithoutAutoPrechargeFlag() const;
|
||||||
|
|
||||||
// To calculate precharge offset after read or write with auto-precharge
|
// To calculate precharge offset after read or write with auto-precharge
|
||||||
int getPrechargeOffset(const MemorySpecification& memSpec,
|
int64_t getPrechargeOffset(const MemorySpecification& memSpec,
|
||||||
MemCommand::cmds type) const;
|
MemCommand::cmds type) const;
|
||||||
|
|
||||||
// To check for equivalence
|
// To check for equivalence
|
||||||
|
@ -136,19 +136,35 @@ class MemCommand {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned int nCommands = 18;
|
static const unsigned int nCommands = 19;
|
||||||
|
|
||||||
static std::string* getCommandTypeStrings()
|
static std::string* getCommandTypeStrings()
|
||||||
{
|
{
|
||||||
static std::string type_map[nCommands] = { "ACT", "RD", "WR", "PRE", "REF",
|
static std::string type_map[nCommands] = { "ACT",
|
||||||
"END", "RDA", "WRA", "PREA", "PDN_F_PRE","PDN_S_PRE", "PDN_F_ACT",
|
"RD",
|
||||||
"PDN_S_ACT", "PUP_PRE", "PUP_ACT", "SREN", "SREX", "NOP" };
|
"WR",
|
||||||
|
"PRE",
|
||||||
|
"REF",
|
||||||
|
"END",
|
||||||
|
"RDA",
|
||||||
|
"WRA",
|
||||||
|
"PREA",
|
||||||
|
"PDN_F_PRE",
|
||||||
|
"PDN_S_PRE",
|
||||||
|
"PDN_F_ACT",
|
||||||
|
"PDN_S_ACT",
|
||||||
|
"PUP_PRE",
|
||||||
|
"PUP_ACT",
|
||||||
|
"SREN",
|
||||||
|
"SREX",
|
||||||
|
"NOP",
|
||||||
|
"UNINITIALIZED" };
|
||||||
|
|
||||||
return type_map;
|
return type_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To identify command type from name
|
// To identify command type from name
|
||||||
static cmds getTypeFromName(const std::string name)
|
static cmds getTypeFromName(const std::string& name)
|
||||||
{
|
{
|
||||||
std::string* typeStrings = getCommandTypeStrings();
|
std::string* typeStrings = getCommandTypeStrings();
|
||||||
|
|
||||||
|
@ -165,7 +181,7 @@ class MemCommand {
|
||||||
private:
|
private:
|
||||||
MemCommand::cmds type;
|
MemCommand::cmds type;
|
||||||
unsigned bank;
|
unsigned bank;
|
||||||
double timestamp;
|
int64_t timestamp;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // ifndef MEMCOMMAND_H
|
#endif // ifndef MEMCOMMAND_H
|
||||||
|
|
|
@ -31,10 +31,12 @@
|
||||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*
|
*
|
||||||
* Authors: Karthik Chandrasekar
|
* Authors: Karthik Chandrasekar, Sven Goossens
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "Parametrisable.h"
|
#include "Parametrisable.h"
|
||||||
|
|
||||||
namespace Data {
|
namespace Data {
|
||||||
|
@ -44,35 +46,35 @@ class MemTimingSpec : public virtual Parametrisable {
|
||||||
void processParameters();
|
void processParameters();
|
||||||
|
|
||||||
double clkMhz;
|
double clkMhz;
|
||||||
unsigned RC;
|
int64_t RC;
|
||||||
unsigned RCD;
|
int64_t RCD;
|
||||||
unsigned CCD;
|
int64_t CCD;
|
||||||
unsigned CCD_S;
|
int64_t CCD_S;
|
||||||
unsigned CCD_L;
|
int64_t CCD_L;
|
||||||
unsigned RRD;
|
int64_t RRD;
|
||||||
unsigned RRD_S;
|
int64_t RRD_S;
|
||||||
unsigned RRD_L;
|
int64_t RRD_L;
|
||||||
unsigned FAW;
|
int64_t FAW;
|
||||||
unsigned TAW;
|
int64_t TAW;
|
||||||
unsigned WTR;
|
int64_t WTR;
|
||||||
unsigned WTR_S;
|
int64_t WTR_S;
|
||||||
unsigned WTR_L;
|
int64_t WTR_L;
|
||||||
unsigned REFI;
|
int64_t REFI;
|
||||||
unsigned RL;
|
int64_t RL;
|
||||||
unsigned RP;
|
int64_t RP;
|
||||||
unsigned RFC;
|
int64_t RFC;
|
||||||
unsigned RAS;
|
int64_t RAS;
|
||||||
unsigned WL;
|
int64_t WL;
|
||||||
unsigned AL;
|
int64_t AL;
|
||||||
unsigned DQSCK;
|
int64_t DQSCK;
|
||||||
unsigned RTP;
|
int64_t RTP;
|
||||||
unsigned WR;
|
int64_t WR;
|
||||||
unsigned XP;
|
int64_t XP;
|
||||||
unsigned XPDLL;
|
int64_t XPDLL;
|
||||||
unsigned XS;
|
int64_t XS;
|
||||||
unsigned XSDLL;
|
int64_t XSDLL;
|
||||||
unsigned CKE;
|
int64_t CKE;
|
||||||
unsigned CKESR;
|
int64_t CKESR;
|
||||||
double clkPeriod;
|
double clkPeriod;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,23 +37,24 @@
|
||||||
|
|
||||||
#include "MemoryPowerModel.h"
|
#include "MemoryPowerModel.h"
|
||||||
|
|
||||||
#include <cmath> // For pow
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <cmath> // For pow
|
||||||
|
#include <iostream> // fmtflags
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
|
|
||||||
// Calculate energy and average power consumption for the given command trace
|
// Calculate energy and average power consumption for the given command trace
|
||||||
|
|
||||||
void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
|
||||||
const CommandAnalysis& counters,
|
const CommandAnalysis& c,
|
||||||
int term)
|
int term)
|
||||||
{
|
{
|
||||||
MemTimingSpec& t = memSpec.memTimingSpec;
|
const MemTimingSpec& t = memSpec.memTimingSpec;
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
MemPowerSpec& mps = memSpec.memPowerSpec;
|
const MemPowerSpec& mps = memSpec.memPowerSpec;
|
||||||
|
|
||||||
energy.act_energy = 0.0;
|
energy.act_energy = 0.0;
|
||||||
energy.pre_energy = 0.0;
|
energy.pre_energy = 0.0;
|
||||||
|
@ -102,16 +103,16 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
||||||
// 1 DQS and 1 DM pin is associated with every data byte
|
// 1 DQS and 1 DM pin is associated with every data byte
|
||||||
int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8;
|
int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8;
|
||||||
// Size of one clock period for the data bus.
|
// Size of one clock period for the data bus.
|
||||||
double ddrPeriod = t.clkPeriod / memArchSpec.dataRate;
|
double ddrPeriod = t.clkPeriod / static_cast<double>(memArchSpec.dataRate);
|
||||||
|
|
||||||
// Read IO power is consumed by each DQ (data) and DQS (data strobe) pin
|
// Read IO power is consumed by each DQ (data) and DQS (data strobe) pin
|
||||||
energy.read_io_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
|
energy.read_io_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
|
||||||
ddrPeriod,
|
ddrPeriod,
|
||||||
power.IO_power,
|
power.IO_power,
|
||||||
dqPlusDqsBits);
|
dqPlusDqsBits);
|
||||||
|
|
||||||
// Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM
|
// Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM
|
||||||
energy.write_term_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
|
energy.write_term_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
|
||||||
ddrPeriod,
|
ddrPeriod,
|
||||||
power.WR_ODT_power,
|
power.WR_ODT_power,
|
||||||
dqPlusDqsPlusMaskBits);
|
dqPlusDqsPlusMaskBits);
|
||||||
|
@ -119,14 +120,14 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
||||||
if (memArchSpec.nbrOfRanks > 1) {
|
if (memArchSpec.nbrOfRanks > 1) {
|
||||||
// Termination power consumed in the idle rank during reads on the active
|
// Termination power consumed in the idle rank during reads on the active
|
||||||
// rank by each DQ (data) and DQS (data strobe) pin.
|
// rank by each DQ (data) and DQS (data strobe) pin.
|
||||||
energy.read_oterm_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength,
|
energy.read_oterm_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
|
||||||
ddrPeriod,
|
ddrPeriod,
|
||||||
power.TermRD_power,
|
power.TermRD_power,
|
||||||
dqPlusDqsBits);
|
dqPlusDqsBits);
|
||||||
|
|
||||||
// Termination power consumed in the idle rank during writes on the active
|
// Termination power consumed in the idle rank during writes on the active
|
||||||
// rank by each DQ (data), DQS (data strobe) and DM (data mask) pin.
|
// rank by each DQ (data), DQS (data strobe) and DM (data mask) pin.
|
||||||
energy.write_oterm_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength,
|
energy.write_oterm_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
|
||||||
ddrPeriod,
|
ddrPeriod,
|
||||||
power.TermWR_power,
|
power.TermWR_power,
|
||||||
dqPlusDqsPlusMaskBits);
|
dqPlusDqsPlusMaskBits);
|
||||||
|
@ -137,101 +138,101 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
||||||
+ energy.read_oterm_energy + energy.write_oterm_energy;
|
+ energy.read_oterm_energy + energy.write_oterm_energy;
|
||||||
}
|
}
|
||||||
|
|
||||||
total_cycles = counters.actcycles + counters.precycles +
|
total_cycles = c.actcycles + c.precycles +
|
||||||
counters.f_act_pdcycles + counters.f_pre_pdcycles +
|
c.f_act_pdcycles + c.f_pre_pdcycles +
|
||||||
counters.s_act_pdcycles + counters.s_pre_pdcycles + counters.sref_cycles
|
c.s_act_pdcycles + c.s_pre_pdcycles + c.sref_cycles
|
||||||
+ counters.sref_ref_act_cycles + counters.sref_ref_pre_cycles +
|
+ c.sref_ref_act_cycles + c.sref_ref_pre_cycles +
|
||||||
counters.spup_ref_act_cycles + counters.spup_ref_pre_cycles;
|
c.spup_ref_act_cycles + c.spup_ref_pre_cycles;
|
||||||
|
|
||||||
EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
|
EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
|
||||||
|
|
||||||
energy.act_energy = vdd0Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd0 - mps.idd3n);
|
energy.act_energy = vdd0Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd0 - mps.idd3n);
|
||||||
energy.pre_energy = vdd0Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
|
energy.pre_energy = vdd0Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
|
||||||
energy.read_energy = vdd0Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r - mps.idd3n);
|
energy.read_energy = vdd0Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r - mps.idd3n);
|
||||||
energy.write_energy = vdd0Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w - mps.idd3n);
|
energy.write_energy = vdd0Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w - mps.idd3n);
|
||||||
energy.ref_energy = vdd0Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd5 - mps.idd3n);
|
energy.ref_energy = vdd0Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd5 - mps.idd3n);
|
||||||
energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(counters.precycles, mps.idd2n);
|
energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(c.precycles, mps.idd2n);
|
||||||
energy.act_stdby_energy = vdd0Domain.calcTivEnergy(counters.actcycles, mps.idd3n);
|
energy.act_stdby_energy = vdd0Domain.calcTivEnergy(c.actcycles, mps.idd3n);
|
||||||
// Idle energy in the active standby clock cycles
|
// Idle energy in the active standby clock cycles
|
||||||
energy.idle_energy_act = vdd0Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n);
|
energy.idle_energy_act = vdd0Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n);
|
||||||
// Idle energy in the precharge standby clock cycles
|
// Idle energy in the precharge standby clock cycles
|
||||||
energy.idle_energy_pre = vdd0Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n);
|
energy.idle_energy_pre = vdd0Domain.calcTivEnergy(c.idlecycles_pre, mps.idd2n);
|
||||||
// fast-exit active power-down cycles energy
|
// fast-exit active power-down cycles energy
|
||||||
energy.f_act_pd_energy = vdd0Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p1);
|
energy.f_act_pd_energy = vdd0Domain.calcTivEnergy(c.f_act_pdcycles, mps.idd3p1);
|
||||||
// fast-exit precharged power-down cycles energy
|
// fast-exit precharged power-down cycles energy
|
||||||
energy.f_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p1);
|
energy.f_pre_pd_energy = vdd0Domain.calcTivEnergy(c.f_pre_pdcycles, mps.idd2p1);
|
||||||
// slow-exit active power-down cycles energy
|
// slow-exit active power-down cycles energy
|
||||||
energy.s_act_pd_energy = vdd0Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p0);
|
energy.s_act_pd_energy = vdd0Domain.calcTivEnergy(c.s_act_pdcycles, mps.idd3p0);
|
||||||
// slow-exit precharged power-down cycles energy
|
// slow-exit precharged power-down cycles energy
|
||||||
energy.s_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p0);
|
energy.s_pre_pd_energy = vdd0Domain.calcTivEnergy(c.s_pre_pdcycles, mps.idd2p0);
|
||||||
|
|
||||||
// self-refresh cycles energy including a refresh per self-refresh entry
|
// self-refresh cycles energy including a refresh per self-refresh entry
|
||||||
energy.sref_energy = engy_sref(mps.idd6, mps.idd3n,
|
energy.sref_energy = engy_sref(mps.idd6, mps.idd3n,
|
||||||
mps.idd5, mps.vdd,
|
mps.idd5, mps.vdd,
|
||||||
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
|
static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
|
||||||
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
|
static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
|
||||||
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
|
static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
|
||||||
|
|
||||||
// background energy during active auto-refresh cycles in self-refresh
|
// background energy during active auto-refresh cycles in self-refresh
|
||||||
energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p0);
|
energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(c.sref_ref_act_cycles, mps.idd3p0);
|
||||||
// background energy during precharged auto-refresh cycles in self-refresh
|
// background energy during precharged auto-refresh cycles in self-refresh
|
||||||
energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p0);
|
energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(c.sref_ref_pre_cycles, mps.idd2p0);
|
||||||
// background energy during active auto-refresh cycles in self-refresh exit
|
// background energy during active auto-refresh cycles in self-refresh exit
|
||||||
energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n);
|
energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(c.spup_ref_act_cycles, mps.idd3n);
|
||||||
// background energy during precharged auto-refresh cycles in self-refresh exit
|
// background energy during precharged auto-refresh cycles in self-refresh exit
|
||||||
energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n);
|
energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(c.spup_ref_pre_cycles, mps.idd2n);
|
||||||
// self-refresh power-up cycles energy -- included
|
// self-refresh power-up cycles energy -- included
|
||||||
energy.spup_energy = vdd0Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n);
|
energy.spup_energy = vdd0Domain.calcTivEnergy(c.spup_cycles, mps.idd2n);
|
||||||
// active power-up cycles energy - same as active standby -- included
|
// active power-up cycles energy - same as active standby -- included
|
||||||
energy.pup_act_energy = vdd0Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n);
|
energy.pup_act_energy = vdd0Domain.calcTivEnergy(c.pup_act_cycles, mps.idd3n);
|
||||||
// precharged power-up cycles energy - same as precharged standby -- included
|
// precharged power-up cycles energy - same as precharged standby -- included
|
||||||
energy.pup_pre_energy = vdd0Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n);
|
energy.pup_pre_energy = vdd0Domain.calcTivEnergy(c.pup_pre_cycles, mps.idd2n);
|
||||||
|
|
||||||
// similar equations as before to support multiple voltage domains in LPDDR2
|
// similar equations as before to support multiple voltage domains in LPDDR2
|
||||||
// and WIDEIO memories
|
// and WIDEIO memories
|
||||||
if (memArchSpec.twoVoltageDomains) {
|
if (memArchSpec.twoVoltageDomains) {
|
||||||
EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
|
EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
|
||||||
|
|
||||||
energy.act_energy += vdd2Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd02 - mps.idd3n2);
|
energy.act_energy += vdd2Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd02 - mps.idd3n2);
|
||||||
energy.pre_energy += vdd2Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
|
energy.pre_energy += vdd2Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
|
||||||
energy.read_energy += vdd2Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2);
|
energy.read_energy += vdd2Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2);
|
||||||
energy.write_energy += vdd2Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2);
|
energy.write_energy += vdd2Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2);
|
||||||
energy.ref_energy += vdd2Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2);
|
energy.ref_energy += vdd2Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2);
|
||||||
energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(counters.precycles, mps.idd2n2);
|
energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(c.precycles, mps.idd2n2);
|
||||||
energy.act_stdby_energy += vdd2Domain.calcTivEnergy(counters.actcycles, mps.idd3n2);
|
energy.act_stdby_energy += vdd2Domain.calcTivEnergy(c.actcycles, mps.idd3n2);
|
||||||
// Idle energy in the active standby clock cycles
|
// Idle energy in the active standby clock cycles
|
||||||
energy.idle_energy_act += vdd2Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n2);
|
energy.idle_energy_act += vdd2Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n2);
|
||||||
// Idle energy in the precharge standby clock cycles
|
// Idle energy in the precharge standby clock cycles
|
||||||
energy.idle_energy_pre += vdd2Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n2);
|
energy.idle_energy_pre += vdd2Domain.calcTivEnergy(c.idlecycles_pre, mps.idd2n2);
|
||||||
// fast-exit active power-down cycles energy
|
// fast-exit active power-down cycles energy
|
||||||
energy.f_act_pd_energy += vdd2Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p12);
|
energy.f_act_pd_energy += vdd2Domain.calcTivEnergy(c.f_act_pdcycles, mps.idd3p12);
|
||||||
// fast-exit precharged power-down cycles energy
|
// fast-exit precharged power-down cycles energy
|
||||||
energy.f_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p12);
|
energy.f_pre_pd_energy += vdd2Domain.calcTivEnergy(c.f_pre_pdcycles, mps.idd2p12);
|
||||||
// slow-exit active power-down cycles energy
|
// slow-exit active power-down cycles energy
|
||||||
energy.s_act_pd_energy += vdd2Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p02);
|
energy.s_act_pd_energy += vdd2Domain.calcTivEnergy(c.s_act_pdcycles, mps.idd3p02);
|
||||||
// slow-exit precharged power-down cycles energy
|
// slow-exit precharged power-down cycles energy
|
||||||
energy.s_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p02);
|
energy.s_pre_pd_energy += vdd2Domain.calcTivEnergy(c.s_pre_pdcycles, mps.idd2p02);
|
||||||
|
|
||||||
energy.sref_energy += engy_sref(mps.idd62, mps.idd3n2,
|
energy.sref_energy += engy_sref(mps.idd62, mps.idd3n2,
|
||||||
mps.idd52, mps.vdd2,
|
mps.idd52, mps.vdd2,
|
||||||
static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles),
|
static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
|
||||||
static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles),
|
static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
|
||||||
static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod);
|
static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod);
|
||||||
|
|
||||||
// background energy during active auto-refresh cycles in self-refresh
|
// background energy during active auto-refresh cycles in self-refresh
|
||||||
energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p02);
|
energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(c.sref_ref_act_cycles, mps.idd3p02);
|
||||||
// background energy during precharged auto-refresh cycles in self-refresh
|
// background energy during precharged auto-refresh cycles in self-refresh
|
||||||
energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p02);
|
energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(c.sref_ref_pre_cycles, mps.idd2p02);
|
||||||
// background energy during active auto-refresh cycles in self-refresh exit
|
// background energy during active auto-refresh cycles in self-refresh exit
|
||||||
energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n2);
|
energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(c.spup_ref_act_cycles, mps.idd3n2);
|
||||||
// background energy during precharged auto-refresh cycles in self-refresh exit
|
// background energy during precharged auto-refresh cycles in self-refresh exit
|
||||||
energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n2);
|
energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(c.spup_ref_pre_cycles, mps.idd2n2);
|
||||||
// self-refresh power-up cycles energy -- included
|
// self-refresh power-up cycles energy -- included
|
||||||
energy.spup_energy += vdd2Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n2);
|
energy.spup_energy += vdd2Domain.calcTivEnergy(c.spup_cycles, mps.idd2n2);
|
||||||
// active power-up cycles energy - same as active standby -- included
|
// active power-up cycles energy - same as active standby -- included
|
||||||
energy.pup_act_energy += vdd2Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n2);
|
energy.pup_act_energy += vdd2Domain.calcTivEnergy(c.pup_act_cycles, mps.idd3n2);
|
||||||
// precharged power-up cycles energy - same as precharged standby -- included
|
// precharged power-up cycles energy - same as precharged standby -- included
|
||||||
energy.pup_pre_energy += vdd2Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n2);
|
energy.pup_pre_energy += vdd2Domain.calcTivEnergy(c.pup_pre_cycles, mps.idd2n2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// auto-refresh energy during self-refresh cycles
|
// auto-refresh energy during self-refresh cycles
|
||||||
|
@ -244,7 +245,7 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
||||||
// energy components for both ranks (in a dual-rank system)
|
// energy components for both ranks (in a dual-rank system)
|
||||||
energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
|
energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
|
||||||
energy.write_energy + energy.ref_energy + energy.io_term_energy +
|
energy.write_energy + energy.ref_energy + energy.io_term_energy +
|
||||||
memArchSpec.nbrOfRanks * (energy.act_stdby_energy +
|
static_cast<double>(memArchSpec.nbrOfRanks) * (energy.act_stdby_energy +
|
||||||
energy.pre_stdby_energy + energy.sref_energy +
|
energy.pre_stdby_energy + energy.sref_energy +
|
||||||
energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy
|
energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy
|
||||||
+ energy.s_pre_pd_energy + energy.sref_ref_energy + energy.spup_ref_energy);
|
+ energy.s_pre_pd_energy + energy.sref_ref_energy + energy.spup_ref_energy);
|
||||||
|
@ -253,130 +254,100 @@ void MemoryPowerModel::power_calc(MemorySpecification memSpec,
|
||||||
power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
|
power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
|
||||||
} // MemoryPowerModel::power_calc
|
} // MemoryPowerModel::power_calc
|
||||||
|
|
||||||
void MemoryPowerModel::power_print(MemorySpecification memSpec, int term, const CommandAnalysis& counters) const
|
void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term, const CommandAnalysis& c) const
|
||||||
{
|
{
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
|
const uint64_t nRanks = static_cast<uint64_t>(memArchSpec.nbrOfRanks);
|
||||||
|
const char eUnit[] = " pJ";
|
||||||
|
|
||||||
|
ios_base::fmtflags flags = cout.flags();
|
||||||
|
streamsize precision = cout.precision();
|
||||||
cout.precision(0);
|
cout.precision(0);
|
||||||
cout << "* Trace Details:" << endl;
|
cout << "* Trace Details:" << fixed << endl
|
||||||
cout << "Number of Activates: " << fixed << counters.numberofacts << endl;
|
<< endl << "#ACT commands: " << c.numberofacts
|
||||||
cout << "Number of Reads: " << counters.numberofreads << endl;
|
<< endl << "#RD + #RDA commands: " << c.numberofreads
|
||||||
cout << "Number of Writes: " << counters.numberofwrites << endl;
|
<< endl << "#WR + #WRA commands: " << c.numberofwrites
|
||||||
cout << "Number of Precharges: " << counters.numberofpres << endl;
|
/* #PRE commands (precharge all counts a number of #PRE commands equal to the number of active banks) */
|
||||||
cout << "Number of Refreshes: " << counters.numberofrefs << endl;
|
<< endl << "#PRE (+ PREA) commands: " << c.numberofpres
|
||||||
cout << "Number of Active Cycles: " << counters.actcycles << endl;
|
<< endl << "#REF commands: " << c.numberofrefs
|
||||||
cout << " Number of Active Idle Cycles: " << counters.idlecycles_act << endl;
|
<< endl << "#Active Cycles: " << c.actcycles
|
||||||
cout << " Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl;
|
<< endl << " #Active Idle Cycles: " << c.idlecycles_act
|
||||||
cout << " Number of Auto-Refresh Active cycles during Self-Refresh " <<
|
<< endl << " #Active Power-Up Cycles: " << c.pup_act_cycles
|
||||||
"Power-Up: " << counters.spup_ref_act_cycles << endl;
|
<< endl << " #Auto-Refresh Active cycles during Self-Refresh Power-Up: " << c.spup_ref_act_cycles
|
||||||
cout << "Number of Precharged Cycles: " << counters.precycles << endl;
|
<< endl << "#Precharged Cycles: " << c.precycles
|
||||||
cout << " Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl;
|
<< endl << " #Precharged Idle Cycles: " << c.idlecycles_pre
|
||||||
cout << " Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles
|
<< endl << " #Precharged Power-Up Cycles: " << c.pup_pre_cycles
|
||||||
<< endl;
|
<< endl << " #Auto-Refresh Precharged cycles during Self-Refresh Power-Up: " << c.spup_ref_pre_cycles
|
||||||
cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh"
|
<< endl << " #Self-Refresh Power-Up Cycles: " << c.spup_cycles
|
||||||
<< " Power-Up: " << counters.spup_ref_pre_cycles << endl;
|
<< endl << "Total Idle Cycles (Active + Precharged): " << c.idlecycles_act + c.idlecycles_pre
|
||||||
cout << " Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles
|
<< endl << "#Power-Downs: " << c.f_act_pdns + c.s_act_pdns + c.f_pre_pdns + c.s_pre_pdns
|
||||||
<< endl;
|
<< endl << " #Active Fast-exit Power-Downs: " << c.f_act_pdns
|
||||||
cout << "Total Idle Cycles (Active + Precharged): " <<
|
<< endl << " #Active Slow-exit Power-Downs: " << c.s_act_pdns
|
||||||
counters.idlecycles_act + counters.idlecycles_pre << endl;
|
<< endl << " #Precharged Fast-exit Power-Downs: " << c.f_pre_pdns
|
||||||
cout << "Number of Power-Downs: " << counters.f_act_pdns +
|
<< endl << " #Precharged Slow-exit Power-Downs: " << c.s_pre_pdns
|
||||||
counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl;
|
<< endl << "#Power-Down Cycles: " << c.f_act_pdcycles + c.s_act_pdcycles + c.f_pre_pdcycles + c.s_pre_pdcycles
|
||||||
cout << " Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns
|
<< endl << " #Active Fast-exit Power-Down Cycles: " << c.f_act_pdcycles
|
||||||
<< endl;
|
<< endl << " #Active Slow-exit Power-Down Cycles: " << c.s_act_pdcycles
|
||||||
cout << " Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns
|
<< endl << " #Auto-Refresh Active cycles during Self-Refresh: " << c.sref_ref_act_cycles
|
||||||
<< endl;
|
<< endl << " #Precharged Fast-exit Power-Down Cycles: " << c.f_pre_pdcycles
|
||||||
cout << " Number of Precharged Fast-exit Power-Downs: " <<
|
<< endl << " #Precharged Slow-exit Power-Down Cycles: " << c.s_pre_pdcycles
|
||||||
counters.f_pre_pdns << endl;
|
<< endl << " #Auto-Refresh Precharged cycles during Self-Refresh: " << c.sref_ref_pre_cycles
|
||||||
cout << " Number of Precharged Slow-exit Power-Downs: " <<
|
<< endl << "#Auto-Refresh Cycles: " << c.numberofrefs * memTimingSpec.RFC
|
||||||
counters.s_pre_pdns << endl;
|
<< endl << "#Self-Refreshes: " << c.numberofsrefs
|
||||||
cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles +
|
<< endl << "#Self-Refresh Cycles: " << c.sref_cycles
|
||||||
counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl;
|
<< endl << "----------------------------------------"
|
||||||
cout << " Number of Active Fast-exit Power-Down Cycles: " <<
|
<< endl << "Total Trace Length (clock cycles): " << total_cycles
|
||||||
counters.f_act_pdcycles << endl;
|
<< endl << "----------------------------------------" << endl;
|
||||||
cout << " Number of Active Slow-exit Power-Down Cycles: " <<
|
|
||||||
counters.s_act_pdcycles << endl;
|
cout.precision(2);
|
||||||
cout << " Number of Auto-Refresh Active cycles during Self-Refresh: " <<
|
cout << endl << "* Trace Power and Energy Estimates:" << endl
|
||||||
counters.sref_ref_act_cycles << endl;
|
<< endl << "ACT Cmd Energy: " << energy.act_energy << eUnit
|
||||||
cout << " Number of Precharged Fast-exit Power-Down Cycles: " <<
|
<< endl << "PRE Cmd Energy: " << energy.pre_energy << eUnit
|
||||||
counters.f_pre_pdcycles << endl;
|
<< endl << "RD Cmd Energy: " << energy.read_energy << eUnit
|
||||||
cout << " Number of Precharged Slow-exit Power-Down Cycles: " <<
|
<< endl << "WR Cmd Energy: " << energy.write_energy << eUnit;
|
||||||
counters.s_pre_pdcycles << endl;
|
|
||||||
cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh: " <<
|
|
||||||
counters.sref_ref_pre_cycles << endl;
|
|
||||||
cout << "Number of Auto-Refresh Cycles: " << counters.numberofrefs *
|
|
||||||
memTimingSpec.RFC << endl;
|
|
||||||
cout << "Number of Self-Refreshes: " << counters.numberofsrefs << endl;
|
|
||||||
cout << "Number of Self-Refresh Cycles: " << counters.sref_cycles << endl;
|
|
||||||
cout << "----------------------------------------" << endl;
|
|
||||||
cout << "Total Trace Length (clock cycles): " << total_cycles << endl;
|
|
||||||
cout << "----------------------------------------" << endl;
|
|
||||||
cout.precision(2);
|
|
||||||
|
|
||||||
cout << "\n* Trace Power and Energy Estimates:" << endl;
|
|
||||||
cout << "ACT Cmd Energy: " << energy.act_energy << " pJ" << endl;
|
|
||||||
cout << "PRE Cmd Energy: " << energy.pre_energy << " pJ" << endl;
|
|
||||||
cout << "RD Cmd Energy: " << energy.read_energy << " pJ" << endl;
|
|
||||||
cout << "WR Cmd Energy: " << energy.write_energy << " pJ" << endl;
|
|
||||||
if (term) {
|
if (term) {
|
||||||
cout << "RD I/O Energy: " << energy.read_io_energy << " pJ" << endl;
|
cout << "RD I/O Energy: " << energy.read_io_energy << eUnit << endl;
|
||||||
// No Termination for LPDDR/2/3 and DDR memories
|
// No Termination for LPDDR/2/3 and DDR memories
|
||||||
if (memSpec.memArchSpec.termination) {
|
if (memSpec.memArchSpec.termination) {
|
||||||
cout << "WR Termination Energy: " << energy.write_term_energy << " pJ" << endl;
|
cout << "WR Termination Energy: " << energy.write_term_energy << eUnit << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((memArchSpec.nbrOfRanks > 1) && memSpec.memArchSpec.termination) {
|
if (nRanks > 1 && memSpec.memArchSpec.termination) {
|
||||||
cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy
|
cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy << eUnit
|
||||||
<< " pJ" << endl;
|
<< endl << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy << eUnit << endl;
|
||||||
cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy
|
|
||||||
<< " pJ" << endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy <<
|
|
||||||
" pJ" << endl;
|
double nRanksDouble = static_cast<double>(nRanks);
|
||||||
cout << " Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act <<
|
|
||||||
" pJ" << endl;
|
cout << "ACT Stdby Energy: " << nRanksDouble * energy.act_stdby_energy << eUnit
|
||||||
cout << " Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy <<
|
<< endl << " Active Idle Energy: " << nRanksDouble * energy.idle_energy_act << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Active Power-Up Energy: " << nRanksDouble * energy.pup_act_energy << eUnit
|
||||||
cout << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh"
|
<< endl << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_act_energy << eUnit
|
||||||
<< " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy <<
|
<< endl << "PRE Stdby Energy: " << nRanksDouble * energy.pre_stdby_energy << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Precharge Idle Energy: " << nRanksDouble * energy.idle_energy_pre << eUnit
|
||||||
cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy <<
|
<< endl << " Precharged Power-Up Energy: " << nRanksDouble * energy.pup_pre_energy << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: " << nRanksDouble * energy.spup_ref_pre_energy << eUnit
|
||||||
cout << " Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre <<
|
<< endl << " Self-Refresh Power-Up Energy: " << nRanksDouble * energy.spup_energy << eUnit
|
||||||
" pJ" << endl;
|
<< endl << "Total Idle Energy (Active + Precharged): " << nRanksDouble * (energy.idle_energy_act + energy.idle_energy_pre) << eUnit
|
||||||
cout << " Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy <<
|
<< endl << "Total Power-Down Energy: " << nRanksDouble * (energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Fast-Exit Active Power-Down Energy: " << nRanksDouble * energy.f_act_pd_energy << eUnit
|
||||||
cout << " Precharge Stdby Energy during Auto-Refresh cycles " <<
|
<< endl << " Slow-Exit Active Power-Down Energy: " << nRanksDouble * energy.s_act_pd_energy << eUnit
|
||||||
"in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy <<
|
<< endl << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_act_energy << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Fast-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.f_pre_pd_energy << eUnit
|
||||||
cout << " Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy <<
|
<< endl << " Slow-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.s_pre_pd_energy << eUnit
|
||||||
" pJ" << endl;
|
<< endl << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy << eUnit
|
||||||
cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks *
|
<< endl << "Auto-Refresh Energy: " << energy.ref_energy << eUnit
|
||||||
(energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl;
|
<< endl << "Self-Refresh Energy: " << nRanksDouble * energy.sref_energy << eUnit
|
||||||
cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy +
|
<< endl << "----------------------------------------"
|
||||||
energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl;
|
<< endl << "Total Trace Energy: " << energy.total_energy << eUnit
|
||||||
cout << " Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
|
<< endl << "Average Power: " << power.average_power << " mW"
|
||||||
energy.f_act_pd_energy << " pJ" << endl;
|
<< endl << "----------------------------------------" << endl;
|
||||||
cout << " Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks *
|
|
||||||
energy.s_act_pd_energy << " pJ" << endl;
|
cout.flags(flags);
|
||||||
cout << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles "
|
cout.precision(precision);
|
||||||
<< "in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_act_energy <<
|
|
||||||
" pJ" << endl;
|
|
||||||
cout << " Fast-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
|
|
||||||
energy.f_pre_pd_energy << " pJ" << endl;
|
|
||||||
cout << " Slow-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks *
|
|
||||||
energy.s_pre_pd_energy << " pJ" << endl;
|
|
||||||
cout << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh " <<
|
|
||||||
"cycles in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_pre_energy <<
|
|
||||||
" pJ" << endl;
|
|
||||||
cout << "Auto-Refresh Energy: " << energy.ref_energy << " pJ" << endl;
|
|
||||||
cout << "Self-Refresh Energy: " << memArchSpec.nbrOfRanks * energy.sref_energy <<
|
|
||||||
" pJ" << endl;
|
|
||||||
cout << "----------------------------------------" << endl;
|
|
||||||
cout << "Total Trace Energy: " << energy.total_energy << " pJ" << endl;
|
|
||||||
cout << "Average Power: " << power.average_power << " mW" << endl;
|
|
||||||
cout << "----------------------------------------" << endl;
|
|
||||||
} // MemoryPowerModel::power_print
|
} // MemoryPowerModel::power_print
|
||||||
|
|
||||||
// Self-refresh active energy estimation (not including background energy)
|
// Self-refresh active energy estimation (not including background energy)
|
||||||
|
@ -395,11 +366,11 @@ double MemoryPowerModel::engy_sref(double idd6, double idd3n, double idd5,
|
||||||
|
|
||||||
// IO and Termination power calculation based on Micron Power Calculators
|
// IO and Termination power calculation based on Micron Power Calculators
|
||||||
// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW)
|
// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW)
|
||||||
void MemoryPowerModel::io_term_power(MemorySpecification memSpec)
|
void MemoryPowerModel::io_term_power(const MemorySpecification& memSpec)
|
||||||
{
|
{
|
||||||
MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
|
||||||
MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
|
||||||
MemPowerSpec& memPowerSpec = memSpec.memPowerSpec;
|
const MemPowerSpec& memPowerSpec = memSpec.memPowerSpec;
|
||||||
|
|
||||||
power.IO_power = memPowerSpec.ioPower; // in mW
|
power.IO_power = memPowerSpec.ioPower; // in mW
|
||||||
power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW
|
power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW
|
||||||
|
|
|
@ -46,9 +46,9 @@ class MemoryPowerModel {
|
||||||
public:
|
public:
|
||||||
// Calculate energy and average power consumption for the given memory
|
// Calculate energy and average power consumption for the given memory
|
||||||
// command trace
|
// command trace
|
||||||
void power_calc(MemorySpecification memSpec,
|
void power_calc(const MemorySpecification& memSpec,
|
||||||
const CommandAnalysis& counters,
|
const CommandAnalysis& c,
|
||||||
int term);
|
int term);
|
||||||
|
|
||||||
// Used to calculate self-refresh active energy
|
// Used to calculate self-refresh active energy
|
||||||
static double engy_sref(double idd6,
|
static double engy_sref(double idd6,
|
||||||
|
@ -145,12 +145,12 @@ class MemoryPowerModel {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Print the power and energy
|
// Print the power and energy
|
||||||
void power_print(MemorySpecification memSpec,
|
void power_print(const MemorySpecification& memSpec,
|
||||||
int term,
|
int term,
|
||||||
const CommandAnalysis& counters) const;
|
const CommandAnalysis& c) const;
|
||||||
|
|
||||||
// To derive IO and Termination Power measures using DRAM specification
|
// To derive IO and Termination Power measures using DRAM specification
|
||||||
void io_term_power(MemorySpecification memSpec);
|
void io_term_power(const MemorySpecification& memSpec);
|
||||||
|
|
||||||
Energy energy;
|
Energy energy;
|
||||||
Power power;
|
Power power;
|
||||||
|
|
|
@ -106,7 +106,8 @@ class MemoryType {
|
||||||
return val == LPDDR ||
|
return val == LPDDR ||
|
||||||
val == LPDDR2 ||
|
val == LPDDR2 ||
|
||||||
val == LPDDR3 ||
|
val == LPDDR3 ||
|
||||||
val == WIDEIO_SDR;
|
val == WIDEIO_SDR ||
|
||||||
|
val == DDR4;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isDDRFamily() const
|
bool isDDRFamily() const
|
||||||
|
@ -132,9 +133,11 @@ class MemoryType {
|
||||||
|
|
||||||
double getCapacitance() const
|
double getCapacitance() const
|
||||||
{
|
{
|
||||||
// LPDDR/2/3 and DDR memories only have IO Power (no ODT)
|
// LPDDR1/2 memories only have IO Power (no ODT)
|
||||||
// Conservative estimates based on Micron Mobile LPDDR2 Power Calculator
|
// LPDDR3 has optional ODT, but it is typically not used (reflections are elimitated by other means (layout))
|
||||||
// LPDDR/2/3 IO Capacitance in mF
|
// The capacitance values are conservative and based on Micron Mobile LPDDR2 Power Calculator
|
||||||
|
|
||||||
|
// LPDDR/2/3 IO Capacitance in mF
|
||||||
if (val == LPDDR) {
|
if (val == LPDDR) {
|
||||||
return 0.0000000045;
|
return 0.0000000045;
|
||||||
} else if (val == LPDDR2) {
|
} else if (val == LPDDR2) {
|
||||||
|
|
|
@ -42,14 +42,19 @@
|
||||||
using namespace Data;
|
using namespace Data;
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
TraceParser::TraceParser(int64_t nbrOfBanks) :
|
||||||
|
counters(nbrOfBanks)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Data::MemCommand TraceParser::parseLine(std::string line)
|
Data::MemCommand TraceParser::parseLine(std::string line)
|
||||||
{
|
{
|
||||||
MemCommand memcmd;
|
MemCommand memcmd(MemCommand::UNINITIALIZED, 0, 0);
|
||||||
istringstream linestream(line);
|
istringstream linestream(line);
|
||||||
string item;
|
string item;
|
||||||
double item_val;
|
int64_t item_val;
|
||||||
unsigned itemnum = 0;
|
unsigned itemnum = 0;
|
||||||
MemCommand::cmds type = MemCommand::NOP; // Initialized to prevent warning
|
|
||||||
|
|
||||||
while (getline(linestream, item, ',')) {
|
while (getline(linestream, item, ',')) {
|
||||||
if (itemnum == 0) {
|
if (itemnum == 0) {
|
||||||
|
@ -62,10 +67,8 @@ Data::MemCommand TraceParser::parseLine(std::string line)
|
||||||
} else if (itemnum == 2) {
|
} else if (itemnum == 2) {
|
||||||
stringstream bank(item);
|
stringstream bank(item);
|
||||||
bank >> item_val;
|
bank >> item_val;
|
||||||
memcmd.setType(type);
|
|
||||||
memcmd.setBank(static_cast<unsigned>(item_val));
|
memcmd.setBank(static_cast<unsigned>(item_val));
|
||||||
}
|
}
|
||||||
type = memcmd.getType();
|
|
||||||
itemnum++;
|
itemnum++;
|
||||||
}
|
}
|
||||||
return memcmd;
|
return memcmd;
|
||||||
|
@ -90,13 +93,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
|
||||||
cmd_list.push_back(cmdline);
|
cmd_list.push_back(cmdline);
|
||||||
nCommands++;
|
nCommands++;
|
||||||
if (nCommands == window) {
|
if (nCommands == window) {
|
||||||
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
|
counters.getCommands(memSpec, cmd_list, lastupdate);
|
||||||
nCommands = 0;
|
nCommands = 0;
|
||||||
cmd_list.clear();
|
cmd_list.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastupdate = true;
|
lastupdate = true;
|
||||||
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
|
counters.getCommands(memSpec, cmd_list, lastupdate);
|
||||||
cmd_list.clear();
|
cmd_list.clear();
|
||||||
pwr_trace.close();
|
pwr_trace.close();
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,13 +109,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
|
||||||
cmd_list.push_back(cmdline);
|
cmd_list.push_back(cmdline);
|
||||||
nCommands++;
|
nCommands++;
|
||||||
if (nCommands == window) {
|
if (nCommands == window) {
|
||||||
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
|
counters.getCommands(memSpec, cmd_list, lastupdate);
|
||||||
nCommands = 0;
|
nCommands = 0;
|
||||||
cmd_list.clear();
|
cmd_list.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
lastupdate = true;
|
lastupdate = true;
|
||||||
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate);
|
counters.getCommands(memSpec, cmd_list, lastupdate);
|
||||||
cmd_list.clear();
|
cmd_list.clear();
|
||||||
}
|
}
|
||||||
counters.clear();
|
counters.clear();
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
|
|
||||||
class TraceParser {
|
class TraceParser {
|
||||||
public:
|
public:
|
||||||
|
TraceParser(int64_t nbrOfBanks);
|
||||||
// list of parsed commands
|
// list of parsed commands
|
||||||
std::vector<Data::MemCommand> cmd_list;
|
std::vector<Data::MemCommand> cmd_list;
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <typeinfo>
|
|
||||||
|
|
||||||
#define MILLION 1000000
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T fromString(const std::string& s,
|
T fromString(const std::string& s,
|
||||||
|
@ -54,7 +52,7 @@ throw(std::runtime_error)
|
||||||
T t;
|
T t;
|
||||||
|
|
||||||
if (!(is >> f >> t)) {
|
if (!(is >> f >> t)) {
|
||||||
throw std::runtime_error("fromString cannot convert " + s);
|
throw std::runtime_error("Cannot convert string");
|
||||||
}
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
|
|
@ -52,13 +52,13 @@ libDRAMPower::~libDRAMPower()
|
||||||
|
|
||||||
void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp)
|
void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp)
|
||||||
{
|
{
|
||||||
MemCommand cmd(type, static_cast<unsigned>(bank), static_cast<double>(timestamp));
|
MemCommand cmd(type, static_cast<unsigned>(bank), timestamp);
|
||||||
cmdList.push_back(cmd);
|
cmdList.push_back(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void libDRAMPower::updateCounters(bool lastUpdate)
|
void libDRAMPower::updateCounters(bool lastUpdate)
|
||||||
{
|
{
|
||||||
counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmdList, lastUpdate);
|
counters.getCommands(memSpec, cmdList, lastUpdate);
|
||||||
cmdList.clear();
|
cmdList.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,6 +72,11 @@ void libDRAMPower::clearState()
|
||||||
counters.clear();
|
counters.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libDRAMPower::clearCounters(int64_t timestamp)
|
||||||
|
{
|
||||||
|
counters.clearStats(timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
|
const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const
|
||||||
{
|
{
|
||||||
return mpm.energy;
|
return mpm.energy;
|
||||||
|
|
|
@ -56,6 +56,8 @@ class libDRAMPower {
|
||||||
|
|
||||||
void updateCounters(bool lastUpdate);
|
void updateCounters(bool lastUpdate);
|
||||||
|
|
||||||
|
void clearCounters(int64_t timestamp);
|
||||||
|
|
||||||
void clearState();
|
void clearState();
|
||||||
|
|
||||||
void calcEnergy();
|
void calcEnergy();
|
||||||
|
|
|
@ -79,7 +79,8 @@ int main(int argc, char* argv[])
|
||||||
test.doCommand(MemCommand::RDA,0,210);
|
test.doCommand(MemCommand::RDA,0,210);
|
||||||
test.doCommand(MemCommand::ACT,4,232);
|
test.doCommand(MemCommand::ACT,4,232);
|
||||||
test.doCommand(MemCommand::WRA,4,247);
|
test.doCommand(MemCommand::WRA,4,247);
|
||||||
test.doCommand(MemCommand::PDN_F_ACT,3,248);
|
// Need at least tWRAPDEN = AL + CWL + BL/2 + WR + 1 cycles between WR and PDN_F_PRE
|
||||||
|
test.doCommand(MemCommand::PDN_F_PRE,3,265);
|
||||||
|
|
||||||
//set bool to true when this is the last update of the counters
|
//set bool to true when this is the last update of the counters
|
||||||
test.updateCounters(true);
|
test.updateCounters(true);
|
||||||
|
@ -106,7 +107,7 @@ int main(int argc, char* argv[])
|
||||||
//test.getEnergy().act_stdby_energy
|
//test.getEnergy().act_stdby_energy
|
||||||
std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
|
std::cout << "ACT Std Energy" << "\t" << test.getEnergy().act_stdby_energy << endl;
|
||||||
//total active standby energy for both ranks
|
//total active standby energy for both ranks
|
||||||
std::cout << "ACT Std Energy total ranks" << "\t" << memSpec.memArchSpec.nbrOfRanks *
|
std::cout << "ACT Std Energy total ranks" << "\t" << static_cast<double>(memSpec.memArchSpec.nbrOfRanks) *
|
||||||
test.getEnergy().act_stdby_energy << "\n" ;
|
test.getEnergy().act_stdby_energy << "\n" ;
|
||||||
std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
|
std::cout << "PRE Std Energy" << "\t" << test.getEnergy().pre_stdby_energy << endl;
|
||||||
std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;
|
std::cout << "Total Energy" << "\t" << test.getEnergy().total_energy << endl;
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
* Ani Udipi
|
* Ani Udipi
|
||||||
* Neha Agarwal
|
* Neha Agarwal
|
||||||
* Omar Naji
|
* Omar Naji
|
||||||
|
* Matthias Jung
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -862,7 +863,7 @@ class DRAMCtrl : public AbstractMemory
|
||||||
*/
|
*/
|
||||||
static bool sortTime(const Data::MemCommand& m1,
|
static bool sortTime(const Data::MemCommand& m1,
|
||||||
const Data::MemCommand& m2) {
|
const Data::MemCommand& m2) {
|
||||||
return m1.getTime() < m2.getTime();
|
return m1.getTimeInt64() < m2.getTimeInt64();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue