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