summaryrefslogtreecommitdiff
path: root/ext/drampower/src
diff options
context:
space:
mode:
Diffstat (limited to 'ext/drampower/src')
-rw-r--r--ext/drampower/src/CAHelpers.cc118
-rw-r--r--ext/drampower/src/CmdHandlers.cc625
-rw-r--r--ext/drampower/src/CommandAnalysis.cc500
-rw-r--r--ext/drampower/src/CommandAnalysis.h114
-rw-r--r--ext/drampower/src/MemBankWiseParams.cc161
-rw-r--r--ext/drampower/src/MemBankWiseParams.h79
-rw-r--r--ext/drampower/src/MemCommand.h59
-rw-r--r--ext/drampower/src/MemPowerSpec.cc2
-rw-r--r--ext/drampower/src/MemPowerSpec.h1
-rw-r--r--ext/drampower/src/MemTimingSpec.cc2
-rw-r--r--ext/drampower/src/MemTimingSpec.h1
-rw-r--r--ext/drampower/src/MemoryPowerModel.cc275
-rw-r--r--ext/drampower/src/MemoryPowerModel.h80
-rw-r--r--ext/drampower/src/TraceParser.cc14
-rw-r--r--ext/drampower/src/TraceParser.h2
-rw-r--r--ext/drampower/src/libdrampower/LibDRAMPower.cc37
-rw-r--r--ext/drampower/src/libdrampower/LibDRAMPower.h25
17 files changed, 1567 insertions, 528 deletions
diff --git a/ext/drampower/src/CAHelpers.cc b/ext/drampower/src/CAHelpers.cc
new file mode 100644
index 000000000..e7df88318
--- /dev/null
+++ b/ext/drampower/src/CAHelpers.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2012-2014, TU Delft
+ * Copyright (c) 2012-2014, TU Eindhoven
+ * Copyright (c) 2012-2014, TU Kaiserslautern
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <cstdio>
+#include <algorithm> // std::count
+#include <string>
+
+#include "CommandAnalysis.h"
+
+using std::cerr;
+using std::endl;
+using std::string;
+
+using namespace Data;
+
+
+// To get the time of completion of the issued command
+// Derived based on JEDEC specifications
+
+int64_t CommandAnalysis::timeToCompletion(MemCommand::cmds type)
+{
+ int64_t offset = 0;
+ const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
+ const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
+
+ if (type == MemCommand::RD) {
+ offset = memTimingSpec.RL +
+ memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
+ memArchSpec.dataRate);
+ } else if (type == MemCommand::WR) {
+ offset = memTimingSpec.WL +
+ (memArchSpec.burstLength / memArchSpec.dataRate) +
+ memTimingSpec.WR;
+ } else if (type == MemCommand::ACT) {
+ offset = memTimingSpec.RCD;
+ } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
+ offset = memTimingSpec.RP;
+ }
+ return offset;
+} // CommandAnalysis::timeToCompletion
+
+
+// Returns the number of active banks based on the bank_state vector.
+unsigned CommandAnalysis::get_num_active_banks(void)
+{
+ return (unsigned)std::count(bank_state.begin(), bank_state.end(), BANK_ACTIVE);
+}
+
+// Naming-standard compliant wrapper
+unsigned CommandAnalysis::nActiveBanks(void)
+{
+ return CommandAnalysis::get_num_active_banks();
+}
+
+bool CommandAnalysis::isPrecharged(unsigned bank)
+{
+ return bank_state[bank] == BANK_PRECHARGED;
+}
+
+void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, unsigned bank)
+{
+ if (get_num_active_banks() != 0) {
+ printWarning(warning, type, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, unsigned bank)
+{
+ if (get_num_active_banks() == 0) {
+ printWarning(warning, type, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::printWarningIfPoweredDown(const string& warning, int type, int64_t timestamp, unsigned bank)
+{
+ if (mem_state != 0) {
+ printWarning(warning, type, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::printWarning(const string& warning, int type, int64_t timestamp, unsigned bank)
+{
+ cerr << "WARNING: " << warning << endl;
+ cerr << "Command: " << type << ", Timestamp: " << timestamp <<
+ ", Bank: " << bank << endl;
+}
diff --git a/ext/drampower/src/CmdHandlers.cc b/ext/drampower/src/CmdHandlers.cc
new file mode 100644
index 000000000..f99917d21
--- /dev/null
+++ b/ext/drampower/src/CmdHandlers.cc
@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2012-2014, TU Delft
+ * Copyright (c) 2012-2014, TU Eindhoven
+ * Copyright (c) 2012-2014, TU Kaiserslautern
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "CommandAnalysis.h"
+
+using std::cerr;
+using std::endl;
+using std::max;
+
+using namespace Data;
+
+
+int64_t zero_guard(int64_t cycles_in, const char* warning)
+{
+ // Calculate max(0, cycles_in)
+ int64_t zero = 0;
+ if (warning != nullptr && cycles_in < 0) {
+ // This line is commented out for now, we will attempt to remove the situations where
+ // these warnings trigger later.
+ // cerr << "WARNING: " << warning << endl;
+ }
+ return max(zero, cycles_in);
+}
+
+void CommandAnalysis::handleAct(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::ACT, 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.
+ // If the bank is already active ignore the command and generate a
+ // warning.
+ if (isPrecharged(bank)) {
+ numberofactsBanks[bank]++;
+
+ if (nActiveBanks() == 0) {
+ // Here a memory state transition to ACT is happening. Save the
+ // number of cycles in precharge state (increment the counter).
+ first_act_cycle = timestamp;
+ precycles += zero_guard(timestamp - last_pre_cycle, "1 last_pre_cycle is in the future.");
+ idle_pre_update(timestamp, latest_pre_cycle);
+ }
+
+ bank_state[bank] = BANK_ACTIVE;
+ latest_act_cycle = timestamp;
+ } else {
+ printWarning("Bank is already active!", MemCommand::ACT, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::handleRd(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::RD, timestamp, bank);
+ // If command is RD - update number of reads and read cycle. Check
+ // for active idle cycles (if any).
+ if (isPrecharged(bank)) {
+ printWarning("Bank is not active!", MemCommand::RD, timestamp, bank);
+ }
+ numberofreadsBanks[bank]++;
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+ latest_read_cycle = timestamp;
+}
+
+void CommandAnalysis::handleWr(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::WR, timestamp, bank);
+ // If command is WR - update number of writes and write cycle. Check
+ // for active idle cycles (if any).
+ if (isPrecharged(bank)) {
+ printWarning("Bank is not active!", MemCommand::WR, timestamp, bank);
+ }
+ numberofwritesBanks[bank]++;
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+ latest_write_cycle = timestamp;
+}
+
+void CommandAnalysis::handleRef(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::REF, 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
+ // for active and precharged cycles and idle active and idle
+ // precharged cycles before refresh. Change memory state to 0.
+ printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", MemCommand::REF, timestamp, bank);
+ numberofrefs++;
+ idle_pre_update(timestamp, latest_pre_cycle);
+ first_act_cycle = timestamp;
+ std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
+ precycles += zero_guard(timestamp - last_pre_cycle, "2 last_pre_cycle is in the future.");
+ last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
+ latest_pre_cycle = last_pre_cycle;
+ actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
+ for (auto &e : actcyclesBanks) {
+ e += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
+ }
+ for (auto& bs : bank_state) {
+ bs = BANK_PRECHARGED;
+ }
+}
+
+void CommandAnalysis::handleRefB(unsigned bank, int64_t timestamp)
+{
+ // A REFB command requires a previous PRE command.
+ if (isPrecharged(bank)) {
+ // This previous PRE command handler is also responsible for keeping the
+ // memory state updated.
+ // Here we consider that the memory state is not changed in order to keep
+ // things simple, since the transition from PRE to ACT state takes time.
+ numberofrefbBanks[bank]++;
+ // Length of the refresh: here we have an approximation, we consider tRP
+ // also as act cycles because the bank will be precharged (stable) after
+ // tRP.
+ actcyclesBanks[bank] += memSpec.memTimingSpec.RAS + memSpec.memTimingSpec.RP;
+ } else {
+ printWarning("Bank must be precharged for REFB!", MemCommand::REFB, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::handlePre(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PRE, 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
+ // (i.e., this is the last active bank).
+ // If the bank is already precharged ignore the command and generate a
+ // warning.
+
+ // Precharge only if the target bank is active
+ if (bank_state[bank] == BANK_ACTIVE) {
+ numberofpresBanks[bank]++;
+ actcyclesBanks[bank] += zero_guard(timestamp - first_act_cycle_banks[bank], "first_act_cycle is in the future (bank).");
+ // Since we got here, at least one bank is active
+ assert(nActiveBanks() != 0);
+
+ if (nActiveBanks() == 1) {
+ // This is the last active bank. Therefore, here a memory state
+ // transition to PRE is happening. Let's increment the active cycle
+ // counter.
+ actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
+ last_pre_cycle = timestamp;
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+ }
+
+ bank_state[bank] = BANK_PRECHARGED;
+ latest_pre_cycle = timestamp;
+ } else {
+ printWarning("Bank is already precharged!", MemCommand::PRE, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::handlePreA(unsigned bank, int64_t timestamp)
+{
+ printWarningIfPoweredDown("Command issued while in power-down mode.", MemCommand::PREA, timestamp, bank);
+ // If command is explicit PREA (precharge all banks) - update
+ // number of precharges by the number of active banks, update the bank
+ // state of all banks to PRE and set the precharge cycle (the cycle in
+ // which the memory state changes from ACT to PRE, aka last_pre_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 (nActiveBanks() > 0) {
+ // Active banks are being precharged
+ // At least one bank was active, therefore the current memory state is
+ // ACT. Since all banks are being precharged a memory state transition
+ // to PRE is happening. Add to the counter the amount of cycles the
+ // memory remained in the ACT state.
+
+ actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
+ last_pre_cycle = timestamp;
+
+ for (unsigned b = 0; b < num_banks; b++) {
+ if (bank_state[b] == BANK_ACTIVE) {
+ // Active banks are being precharged
+ numberofpresBanks[b] += 1;
+ actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
+ }
+ }
+
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+
+ latest_pre_cycle = timestamp;
+ // Reset the state for all banks to precharged.
+ for (auto& bs : bank_state) {
+ bs = BANK_PRECHARGED;
+ }
+ } else {
+ printWarning("All banks are already precharged!", MemCommand::PREA, timestamp, bank);
+ }
+}
+
+void CommandAnalysis::handlePdnFAct(unsigned bank, int64_t timestamp)
+{
+ // If command is fast-exit active power-down - update number of
+ // power-downs, set the power-down cycle and the memory mode to
+ // fast-exit active power-down. Save states of all the banks from
+ // the cycle before entering active power-down, to be returned to
+ // after powering-up. Update active and active idle cycles.
+ printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_F_ACT, timestamp, bank);
+ f_act_pdns++;
+ last_bank_state = bank_state;
+ pdn_cycle = timestamp;
+ actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
+ for (unsigned b = 0; b < num_banks; b++) {
+ if (bank_state[b] == BANK_ACTIVE) {
+ actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
+ }
+ }
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+ mem_state = CommandAnalysis::MS_PDN_F_ACT;
+}
+
+void CommandAnalysis::handlePdnSAct(unsigned bank, int64_t timestamp)
+{
+ // If command is slow-exit active power-down - update number of
+ // power-downs, set the power-down cycle and the memory mode to
+ // slow-exit active power-down. Save states of all the banks from
+ // the cycle before entering active power-down, to be returned to
+ // after powering-up. Update active and active idle cycles.
+ printWarningIfNotActive("All banks are precharged! Incorrect use of Active Power-Down.", MemCommand::PDN_S_ACT, timestamp, bank);
+ s_act_pdns++;
+ last_bank_state = bank_state;
+ pdn_cycle = timestamp;
+ actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future.");
+ for (unsigned b = 0; b < num_banks; b++) {
+ if (bank_state[b] == BANK_ACTIVE) {
+ actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank).");
+ }
+ }
+ idle_act_update(latest_read_cycle, latest_write_cycle, latest_act_cycle, timestamp);
+ mem_state = CommandAnalysis::MS_PDN_S_ACT;
+}
+
+void CommandAnalysis::handlePdnFPre(unsigned bank, int64_t timestamp)
+{
+ // If command is fast-exit precharged power-down - update number of
+ // power-downs, set the power-down cycle and the memory mode to
+ // fast-exit precahrged power-down. Update precharged and precharged
+ // idle cycles.
+ printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", MemCommand::PDN_F_PRE, timestamp, bank);
+ f_pre_pdns++;
+ pdn_cycle = timestamp;
+ precycles += zero_guard(timestamp - last_pre_cycle, "3 last_pre_cycle is in the future.");
+ idle_pre_update(timestamp, latest_pre_cycle);
+ mem_state = CommandAnalysis::MS_PDN_F_PRE;
+}
+
+void CommandAnalysis::handlePdnSPre(unsigned bank, int64_t timestamp)
+{
+ // If command is slow-exit precharged power-down - update number of
+ // power-downs, set the power-down cycle and the memory mode to
+ // slow-exit precahrged power-down. Update precharged and precharged
+ // idle cycles.
+ printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", MemCommand::PDN_S_PRE, timestamp, bank);
+ s_pre_pdns++;
+ pdn_cycle = timestamp;
+ precycles += zero_guard(timestamp - last_pre_cycle, "4 last_pre_cycle is in the future.");
+ idle_pre_update(timestamp, latest_pre_cycle);
+ mem_state = CommandAnalysis::MS_PDN_S_PRE;
+}
+
+void CommandAnalysis::handlePupAct(int64_t timestamp)
+{
+ // If command is power-up in the active mode - check the power-down
+ // exit-mode employed (fast or slow), update the number of power-down
+ // and power-up cycles and the latest and first act cycle. Also, reset
+ // all the individual bank states to the respective saved states
+ // before entering power-down.
+ const MemTimingSpec& t = memSpec.memTimingSpec;
+
+ if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
+ f_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
+ pup_act_cycles += t.XP;
+ latest_act_cycle = timestamp;
+ } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
+ s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
+ if (memSpec.memArchSpec.dll == false) {
+ pup_act_cycles += t.XP;
+ latest_act_cycle = timestamp;
+ } else {
+ pup_act_cycles += t.XPDLL - t.RCD;
+ latest_act_cycle = timestamp + zero_guard(t.XPDLL - (2 * t.RCD), "t.XPDLL - (2 * t.RCD) < 0");
+ }
+ } else {
+ cerr << "Incorrect use of Active Power-Up!" << endl;
+ }
+ mem_state = MS_NOT_IN_PD;
+ bank_state = last_bank_state;
+ first_act_cycle = timestamp;
+ std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
+}
+
+void CommandAnalysis::handlePupPre(int64_t timestamp)
+{
+ // If command is power-up in the precharged mode - check the power-down
+ // exit-mode employed (fast or slow), update the number of power-down
+ // and power-up cycles and the latest and last pre cycle.
+ const MemTimingSpec& t = memSpec.memTimingSpec;
+ if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
+ f_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
+ pup_pre_cycles += t.XP;
+ latest_pre_cycle = timestamp;
+ } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
+ s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future.");
+ if (memSpec.memArchSpec.dll == false) {
+ pup_pre_cycles += t.XP;
+ latest_pre_cycle = timestamp;
+ } else {
+ pup_pre_cycles += t.XPDLL - t.RCD;
+ latest_pre_cycle = timestamp + zero_guard(t.XPDLL - t.RCD - t.RP, "t.XPDLL - t.RCD - t.RP");
+ }
+ } else {
+ cerr << "Incorrect use of Precharged Power-Up!" << endl;
+ }
+ mem_state = MS_NOT_IN_PD;
+ last_pre_cycle = timestamp;
+}
+
+void CommandAnalysis::handleSREn(unsigned bank, int64_t timestamp)
+{
+ // If command is self-refresh - update number of self-refreshes,
+ // set memory state to SREF, update precharge and idle precharge
+ // cycles and set the self-refresh cycle.
+ printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", MemCommand::SREN, timestamp, bank);
+ numberofsrefs++;
+ sref_cycle = timestamp;
+ sref_cycle_window = timestamp;
+ sref_ref_pre_cycles_window = 0;
+ sref_ref_act_cycles_window = 0;
+ precycles += zero_guard(timestamp - last_pre_cycle, "5 last_pre_cycle is in the future.");
+ idle_pre_update(timestamp, latest_pre_cycle);
+ mem_state = CommandAnalysis::MS_SREF;
+}
+
+void CommandAnalysis::handleSREx(unsigned bank, int64_t timestamp)
+{
+ // If command is self-refresh exit - update the number of self-refresh
+ // clock cycles, number of active and precharged auto-refresh clock
+ // cycles during self-refresh and self-refresh exit based on the number
+ // of cycles in the self-refresh mode and auto-refresh duration (RFC).
+ // Set the last and latest precharge cycle accordingly and set the
+ // memory state to 0.
+ const MemTimingSpec& t = memSpec.memTimingSpec;
+ if (mem_state != CommandAnalysis::MS_SREF) {
+ cerr << "Incorrect use of Self-Refresh Power-Up!" << endl;
+ }
+ // The total duration of self-refresh is given by the difference between
+ // the current clock cycle and the clock cycle of entering self-refresh.
+ int64_t sref_duration = timestamp - sref_cycle;
+
+ // Negative or zero duration should never happen.
+ if (sref_duration <= 0) {
+ printWarning("Invalid Self-Refresh duration!", MemCommand::SREX, timestamp, bank);
+ sref_duration = 0;
+ }
+
+ // The minimum time that the DRAM must remain in Self-Refresh is CKESR.
+ if (sref_duration < t.CKESR) {
+ printWarning("Self-Refresh duration < CKESR!", MemCommand::SREX, timestamp, bank);
+ }
+
+ if (sref_duration >= t.RFC) {
+ /*
+ * Self-refresh Exit Context 1 (tSREF >= tRFC):
+ * The memory remained in self-refresh for a certain number of clock
+ * cycles greater than a refresh cycle time (RFC). Consequently, the
+ * initial auto-refresh accomplished.
+ *
+ *
+ * SREN # SREX
+ * | # ^
+ * | # |
+ * |<------------------------- tSREF ----------...----->|
+ * | # |
+ * | Initial Auto-Refresh # |
+ * v # |
+ * ------------------------------------#-------...-----------------> t
+ * #
+ * <------------- tRFC -------------->#
+ * <---- (tRFC - tRP) ----><-- tRP -->#
+ * | |
+ * v v
+ * sref_ref_act_cycles sref_ref_pre_cycles
+ *
+ *
+ * Summary:
+ * sref_cycles += tSREF – tRFC
+ * sref_ref_act_cycles += tRFC - tRP
+ * sref_ref_pre_cycles += tRP
+ * spup_ref_act_cycles += 0
+ * spup_ref_pre_cycles += 0
+ *
+ */
+
+ // The initial auto-refresh consumes (IDD5 − IDD3N) over one refresh
+ // period (RFC) from the start of the self-refresh.
+ sref_ref_act_cycles += t.RFC -
+ t.RP - sref_ref_act_cycles_window;
+ sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window;
+ last_pre_cycle = timestamp;
+
+ // The IDD6 current is consumed for the time period spent in the
+ // self-refresh mode, which excludes the time spent in finishing the
+ // initial auto-refresh.
+ if (sref_cycle_window > sref_cycle + t.RFC) {
+ sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future.");
+ } else {
+ sref_cycles += zero_guard(timestamp - sref_cycle - t.RFC, "sref_cycle - t.RFC < 0");
+ }
+
+ // IDD2N current is consumed when exiting the self-refresh state.
+ if (memSpec.memArchSpec.dll == false) {
+ spup_cycles += t.XS;
+ latest_pre_cycle = timestamp + zero_guard(t.XS - t.RP, "t.XS - t.RP < 0");
+ } else {
+ spup_cycles += t.XSDLL - t.RCD;
+ latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - t.RP, "t.XSDLL - t.RCD - t.RP < 0");
+ }
+
+ } else {
+ // Self-refresh Exit Context 2 (tSREF < tRFC):
+ // Exit self-refresh before the completion of the initial
+ // auto-refresh.
+
+ // Number of active cycles needed by an auto-refresh.
+ int64_t ref_act_cycles = t.RFC - t.RP;
+
+ if (sref_duration >= ref_act_cycles) {
+ /*
+ * Self-refresh Exit Context 2A (tSREF < tRFC && tSREF >= tRFC - tRP):
+ * The duration of self-refresh is equal or greater than the number
+ * of active cycles needed by the initial auto-refresh.
+ *
+ *
+ * SREN SREX
+ * | ^ #
+ * | | #
+ * |<------------------ tSREF --------------------->| #
+ * | | #
+ * | Initial Auto-Refresh #
+ * v | #
+ * -----------------------------------------------------------#--> t
+ * #
+ * <------------------------ tRFC -------------------------->#
+ * <------------- (tRFC - tRP)--------------><----- tRP ---->#
+ * | <-----><------->
+ * v | |
+ * sref_ref_act_cycles v v
+ * sref_ref_pre_cycles spup_ref_pre_cycles
+ *
+ *
+ * Summary:
+ * sref_cycles += 0
+ * sref_ref_act_cycles += tRFC - tRP
+ * sref_ref_pre_cycles += tSREF – (tRFC – tRP)
+ * spup_ref_act_cycles += 0
+ * spup_ref_pre_cycles += tRP – sref_ref_pre_cycles
+ *
+ */
+
+ // Number of precharged cycles (zero <= pre_cycles < RP)
+ int64_t pre_cycles = sref_duration - ref_act_cycles - sref_ref_pre_cycles_window;
+
+ sref_ref_act_cycles += ref_act_cycles - sref_ref_act_cycles_window;
+ sref_ref_pre_cycles += pre_cycles;
+
+ // Number of precharged cycles during the self-refresh power-up. It
+ // is at maximum tRP (if pre_cycles is zero).
+ int64_t spup_pre = t.RP - pre_cycles;
+
+ spup_ref_pre_cycles += spup_pre;
+
+ last_pre_cycle = timestamp + spup_pre;
+
+ if (memSpec.memArchSpec.dll == false) {
+ spup_cycles += t.XS - spup_pre;
+ latest_pre_cycle = timestamp + zero_guard(t.XS - spup_pre - t.RP, "t.XS - spup_pre - t.RP < 0");
+ } else {
+ spup_cycles += t.XSDLL - t.RCD - spup_pre;
+ latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - spup_pre - t.RP, "t.XSDLL - t.RCD - spup_pre - t.RP");
+ }
+ } else {
+ /*
+ * Self-refresh Exit Context 2B (tSREF < tRFC - tRP):
+ * self-refresh duration is shorter than the number of active cycles
+ * needed by the initial auto-refresh.
+ *
+ *
+ * SREN SREX
+ * | ^ #
+ * | | #
+ * |<-------------- tSREF ----------->| #
+ * | | #
+ * | Initial Auto-Refresh #
+ * v | #
+ * ------------------------------------------------------------#--> t
+ * #
+ * <------------------------ tRFC --------------------------->#
+ * <-------------- (tRFC - tRP)-------------><------ tRP ---->#
+ * <--------------------------------><------><--------------->
+ * | | |
+ * v v v
+ * sref_ref_act_cycles spup_ref_act_cycles spup_ref_pre_cycles
+ *
+ *
+ * Summary:
+ * sref_cycles += 0
+ * sref_ref_act_cycles += tSREF
+ * sref_ref_pre_cycles += 0
+ * spup_ref_act_cycles += (tRFC – tRP) - tSREF
+ * spup_ref_pre_cycles += tRP
+ *
+ */
+
+ sref_ref_act_cycles += sref_duration - sref_ref_act_cycles_window;
+
+ int64_t spup_act = (t.RFC - t.RP) - sref_duration;
+
+ spup_ref_act_cycles += spup_act;
+ spup_ref_pre_cycles += t.RP;
+
+ last_pre_cycle = timestamp + spup_act + t.RP;
+ if (memSpec.memArchSpec.dll == false) {
+ spup_cycles += t.XS - spup_act - t.RP;
+ latest_pre_cycle = timestamp + zero_guard(t.XS - spup_act - (2 * t.RP), "t.XS - spup_act - (2 * t.RP) < 0");
+ } else {
+ spup_cycles += t.XSDLL - t.RCD - spup_act - t.RP;
+ latest_pre_cycle = timestamp + zero_guard(t.XSDLL - t.RCD - spup_act - (2 * t.RP), "t.XSDLL - t.RCD - spup_act - (2 * t.RP) < 0");
+ }
+ }
+ }
+ mem_state = MS_NOT_IN_PD;
+}
+
+
+void CommandAnalysis::handleNopEnd(int64_t timestamp)
+{
+ // May be optionally used at the end of memory trace for better accuracy
+ // Update all counters based on completion of operations.
+ const MemTimingSpec& t = memSpec.memTimingSpec;
+ for (unsigned b = 0; b < num_banks; b++) {
+ if (bank_state[b] == BANK_ACTIVE) {
+ actcyclesBanks[b] += zero_guard(timestamp - first_act_cycle_banks[b], "first_act_cycle is in the future (bank)");
+ }
+ }
+
+ if (nActiveBanks() > 0 && mem_state == MS_NOT_IN_PD) {
+ actcycles += zero_guard(timestamp - first_act_cycle, "first_act_cycle is in the future");
+ idle_act_update(latest_read_cycle, latest_write_cycle,
+ latest_act_cycle, timestamp);
+ } else if (nActiveBanks() == 0 && mem_state == MS_NOT_IN_PD) {
+ precycles += zero_guard(timestamp - last_pre_cycle, "6 last_pre_cycle is in the future");
+ idle_pre_update(timestamp, latest_pre_cycle);
+ } else if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
+ f_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
+ } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
+ s_act_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
+ } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
+ f_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
+ } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
+ s_pre_pdcycles += zero_guard(timestamp - pdn_cycle, "pdn_cycle is in the future");
+ } else if (mem_state == CommandAnalysis::MS_SREF) {
+ auto rfc_minus_rp = (t.RFC - t.RP);
+
+ if (timestamp > sref_cycle + t.RFC) {
+ if (sref_cycle_window <= sref_cycle + rfc_minus_rp) {
+ sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window;
+ sref_ref_act_cycles_window = rfc_minus_rp;
+ sref_cycle_window = sref_cycle + rfc_minus_rp;
+ }
+ if (sref_cycle_window <= sref_cycle + t.RFC) {
+ sref_ref_pre_cycles += t.RP - sref_ref_pre_cycles_window;
+ sref_ref_pre_cycles_window = t.RP;
+ sref_cycle_window = sref_cycle + t.RFC;
+ }
+ sref_cycles += zero_guard(timestamp - sref_cycle_window, "sref_cycle_window is in the future");
+ } else if (timestamp > sref_cycle + rfc_minus_rp) {
+
+ if (sref_cycle_window <= sref_cycle + rfc_minus_rp) {
+ sref_ref_act_cycles += rfc_minus_rp - sref_ref_act_cycles_window;
+ sref_ref_act_cycles_window = rfc_minus_rp;
+ sref_cycle_window = sref_cycle + rfc_minus_rp;
+ }
+ sref_ref_pre_cycles_window += timestamp - sref_cycle_window;
+ sref_ref_pre_cycles += timestamp - sref_cycle_window;
+ } else {
+ sref_ref_act_cycles_window += timestamp - sref_cycle_window;
+ sref_ref_act_cycles += timestamp - sref_cycle_window;
+ }
+ }
+}
diff --git a/ext/drampower/src/CommandAnalysis.cc b/ext/drampower/src/CommandAnalysis.cc
index e557c2920..b840ab53c 100644
--- a/ext/drampower/src/CommandAnalysis.cc
+++ b/ext/drampower/src/CommandAnalysis.cc
@@ -31,7 +31,13 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji, Sven Goossens
+ * Authors: Karthik Chandrasekar,
+ * Matthias Jung,
+ * Omar Naji,
+ * Sven Goossens,
+ * Éder F. Zulian
+ * Subash Kannoth
+ * Felipe S. Prado
*
*/
@@ -54,30 +60,43 @@ bool commandSorter(const MemCommand& i, const MemCommand& j)
}
}
-CommandAnalysis::CommandAnalysis(const int64_t nbrofBanks)
+CommandAnalysis::CommandAnalysis(const Data::MemorySpecification& memSpec) :
+ memSpec(memSpec)
+
{
+ auto &nBanks = memSpec.memArchSpec.nbrOfBanks;
// Initializing all counters and variables
+ numberofactsBanks.assign(static_cast<size_t>(nBanks), 0);
+ numberofpresBanks.assign(static_cast<size_t>(nBanks), 0);
+ numberofreadsBanks.assign(static_cast<size_t>(nBanks), 0);
+ numberofwritesBanks.assign(static_cast<size_t>(nBanks), 0);
+ actcyclesBanks.assign(static_cast<size_t>(nBanks), 0);
+ numberofrefbBanks.assign(static_cast<size_t>(nBanks), 0);
+
+ first_act_cycle_banks.resize(static_cast<size_t>(nBanks), 0);
+
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;
+ bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED);
+ last_bank_state.resize(static_cast<size_t>(nBanks), BANK_PRECHARGED);
+ mem_state = MS_NOT_IN_PD;
cmd_list.clear();
cached_cmd.clear();
- activation_cycle.resize(static_cast<size_t>(nbrofBanks), 0);
+ activation_cycle.resize(static_cast<size_t>(nBanks), 0);
+ num_banks = nBanks;
}
// function to clear counters
void CommandAnalysis::clearStats(const int64_t timestamp)
{
+ std::fill(numberofactsBanks.begin(), numberofactsBanks.end(), 0);
+ std::fill(numberofpresBanks.begin(), numberofpresBanks.end(), 0);
+ std::fill(numberofreadsBanks.begin(), numberofreadsBanks.end(), 0);
+ std::fill(numberofwritesBanks.begin(), numberofwritesBanks.end(), 0);
+ std::fill(actcyclesBanks.begin(), actcyclesBanks.end(), 0);
- numberofacts = 0;
- numberofpres = 0;
- numberofreads = 0;
- numberofwrites = 0;
numberofrefs = 0;
f_act_pdns = 0;
s_act_pdns = 0;
@@ -104,26 +123,33 @@ void CommandAnalysis::clearStats(const int64_t timestamp)
// reset count references to timestamp so that they are moved
// to start of next stats generation
+ std::fill(first_act_cycle_banks.begin(), first_act_cycle_banks.end(), timestamp);
first_act_cycle = timestamp;
- last_pre_cycle = timestamp;
+
pdn_cycle = timestamp;
- sref_cycle = timestamp;
+ sref_cycle_window = timestamp;
+
end_act_op = timestamp;
end_read_op = timestamp;
end_write_op = timestamp;
- latest_act_cycle = -1;
latest_read_cycle = -1;
latest_write_cycle = -1;
if (timestamp == 0) {
- // set to -1 at beginning of simulation
- latest_pre_cycle = -1;
+ latest_pre_cycle = -1;
+ latest_act_cycle = -1;
+ sref_cycle = 0;
+ last_pre_cycle = 0;
+ sref_ref_act_cycles_window = 0;
+ sref_ref_pre_cycles_window = 0;
} 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;
+ last_pre_cycle = max(timestamp,last_pre_cycle);
+
+ latest_pre_cycle = max(timestamp, latest_pre_cycle);
+
+ if (latest_act_cycle < timestamp)
+ latest_act_cycle = -1;
}
}
@@ -132,8 +158,8 @@ void CommandAnalysis::clear()
{
cached_cmd.clear();
cmd_list.clear();
- last_states.clear();
- bankstate.clear();
+ last_bank_state.clear();
+ bank_state.clear();
}
// Reads through the trace file, identifies the timestamp, command and bank
@@ -141,9 +167,12 @@ void CommandAnalysis::clear()
// precharge to a cached command list and computes the precharge offset from the
// issued command timestamp, when the auto-precharge would kick in
-void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
- std::vector<MemCommand>& list, bool lastupdate)
+void CommandAnalysis::getCommands(std::vector<MemCommand>& list, bool lastupdate, int64_t timestamp)
{
+ if (!next_window_cmd_list.empty()) {
+ list.insert(list.begin(), next_window_cmd_list.begin(), next_window_cmd_list.end());
+ next_window_cmd_list.clear();
+ }
for (size_t i = 0; i < list.size(); ++i) {
MemCommand& cmd = list[i];
MemCommand::cmds cmdType = cmd.getType();
@@ -158,417 +187,94 @@ void CommandAnalysis::getCommands(const Data::MemorySpecification& memSpec,
activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS);
list.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), preTime));
}
+
+ if (!lastupdate && timestamp > 0) {
+ if(cmd.getTimeInt64() > timestamp)
+ {
+ MemCommand nextWindowCmd = list[i];
+ next_window_cmd_list.push_back(nextWindowCmd);
+ list.erase(find(list.begin(), list.end(), cmd));
+ }
+ }
}
sort(list.begin(), list.end(), commandSorter);
if (lastupdate && list.empty() == false) {
// Add cycles at the end of the list
- int64_t t = timeToCompletion(memSpec, list.back().getType()) + list.back().getTimeInt64() - 1;
+ int64_t t = timeToCompletion(list.back().getType()) + list.back().getTimeInt64() - 1;
list.push_back(MemCommand(MemCommand::NOP, 0, t));
}
- evaluate(memSpec, list);
+ evaluateCommands(list);
} // CommandAnalysis::getCommands
-// To get the time of completion of the issued command
-// Derived based on JEDEC specifications
-
-int64_t CommandAnalysis::timeToCompletion(const MemorySpecification&
- memSpec, MemCommand::cmds type)
-{
- int64_t offset = 0;
- const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
- const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
-
- if (type == MemCommand::RD) {
- offset = memTimingSpec.RL +
- memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength /
- memArchSpec.dataRate);
- } else if (type == MemCommand::WR) {
- offset = memTimingSpec.WL +
- (memArchSpec.burstLength / memArchSpec.dataRate) +
- memTimingSpec.WR;
- } else if (type == MemCommand::ACT) {
- offset = memTimingSpec.RCD;
- } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) {
- offset = memTimingSpec.RP;
- }
- return offset;
-} // CommandAnalysis::timeToCompletion
-
// Used to analyse a given list of commands and identify command timings
// and memory state transitions
-void CommandAnalysis::evaluate(const MemorySpecification& memSpec,
- vector<MemCommand>& cmd_list)
+void CommandAnalysis::evaluateCommands(vector<MemCommand>& cmd_list)
{
// for each command identify timestamp, type and bank
for (auto cmd : cmd_list) {
// For command type
int type = cmd.getType();
// For command bank
- int bank = static_cast<int>(cmd.getBank());
+ unsigned bank = cmd.getBank();
// Command Issue timestamp in clock cycles (cc)
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[static_cast<size_t>(bank)] == 1) {
- printWarning("Bank is already active!", type, timestamp, bank);
- }
- 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;
- num_active_banks++;
+ handleAct(bank, timestamp);
} 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[static_cast<size_t>(bank)] == 0) {
- printWarning("Bank is not active!", type, timestamp, bank);
- }
- numberofreads++;
- idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
- latest_act_cycle, timestamp);
- latest_read_cycle = timestamp;
+ handleRd(bank, 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[static_cast<size_t>(bank)] == 0) {
- printWarning("Bank is not active!", type, timestamp, bank);
- }
- numberofwrites++;
- idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
- latest_act_cycle, timestamp);
- latest_write_cycle = timestamp;
+ handleWr(bank, 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
- // for active and precharged cycles and idle active and idle
- // precharged cycles before refresh. Change memory state to 0.
- printWarningIfActive("One or more banks are active! REF requires all banks to be precharged.", type, timestamp, bank);
- numberofrefs++;
- idle_pre_update(memSpec, timestamp, latest_pre_cycle);
- first_act_cycle = timestamp;
- precycles += max(zero, timestamp - last_pre_cycle);
- last_pre_cycle = timestamp + memSpec.memTimingSpec.RFC -
- memSpec.memTimingSpec.RP;
- latest_pre_cycle = last_pre_cycle;
- actcycles += memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
- num_active_banks = 0;
- for (auto& b : bankstate) {
- b = 0;
- }
+ handleRef(bank, timestamp);
+ } else if (type == MemCommand::REFB) {
+ handleRefB(bank, timestamp);
} 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[static_cast<size_t>(bank)] == 1) {
- numberofpres++;
- }
- bankstate[static_cast<size_t>(bank)] = 0;
-
- 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 (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 (num_active_banks > 0) {
- num_active_banks--;
- } else {
- num_active_banks = 0;
- }
+ handlePre(bank, timestamp);
} 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.
- numberofpres += num_active_banks;
-
- 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 (num_active_banks == 0) {
- precycles += max(zero, timestamp - last_pre_cycle);
- idle_pre_update(memSpec, timestamp, latest_pre_cycle);
- }
-
- latest_pre_cycle = timestamp;
- last_pre_cycle = timestamp;
-
- num_active_banks = 0;
-
- for (auto& b : bankstate) {
- b = 0;
- }
+ handlePreA(bank, timestamp);
} else if (type == MemCommand::PDN_F_ACT) {
- // If command is fast-exit active power-down - update number of
- // power-downs, set the power-down cycle and the memory mode to
- // fast-exit active power-down. Save states of all the banks from
- // the cycle before entering active power-down, to be returned to
- // 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++;
- last_states = bankstate;
- pdn_cycle = timestamp;
- actcycles += max(zero, timestamp - first_act_cycle);
- idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
- latest_act_cycle, timestamp);
- mem_state = CommandAnalysis::MS_PDN_F_ACT;
+ handlePdnFAct(bank, timestamp);
} else if (type == MemCommand::PDN_S_ACT) {
- // If command is slow-exit active power-down - update number of
- // power-downs, set the power-down cycle and the memory mode to
- // slow-exit active power-down. Save states of all the banks from
- // the cycle before entering active power-down, to be returned to
- // 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++;
- last_states = bankstate;
- pdn_cycle = timestamp;
- actcycles += max(zero, timestamp - first_act_cycle);
- idle_act_update(memSpec, latest_read_cycle, latest_write_cycle,
- latest_act_cycle, timestamp);
- mem_state = CommandAnalysis::MS_PDN_S_ACT;
+ handlePdnSAct(bank, timestamp);
} else if (type == MemCommand::PDN_F_PRE) {
- // If command is fast-exit precharged power-down - update number of
- // power-downs, set the power-down cycle and the memory mode to
- // fast-exit precahrged power-down. Update precharged and precharged
- // idle cycles.
- printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
- f_pre_pdns++;
- pdn_cycle = timestamp;
- precycles += max(zero, timestamp - last_pre_cycle);
- idle_pre_update(memSpec, timestamp, latest_pre_cycle);
- mem_state = CommandAnalysis::MS_PDN_F_PRE;
+ handlePdnFPre(bank, timestamp);
} else if (type == MemCommand::PDN_S_PRE) {
- // If command is slow-exit precharged power-down - update number of
- // power-downs, set the power-down cycle and the memory mode to
- // slow-exit precahrged power-down. Update precharged and precharged
- // idle cycles.
- printWarningIfActive("One or more banks are active! Incorrect use of Precharged Power-Down.", type, timestamp, bank);
- s_pre_pdns++;
- pdn_cycle = timestamp;
- precycles += max(zero, timestamp - last_pre_cycle);
- idle_pre_update(memSpec, timestamp, latest_pre_cycle);
- mem_state = CommandAnalysis::MS_PDN_S_PRE;
+ handlePdnSPre(bank, timestamp);
} else if (type == MemCommand::PUP_ACT) {
- // If command is power-up in the active mode - check the power-down
- // exit-mode employed (fast or slow), update the number of power-down
- // and power-up cycles and the latest and first act cycle. Also, reset
- // all the individual bank states to the respective saved states
- // before entering power-down.
- if (mem_state == CommandAnalysis::MS_PDN_F_ACT) {
- f_act_pdcycles += max(zero, timestamp - pdn_cycle);
- pup_act_cycles += memSpec.memTimingSpec.XP;
- latest_act_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
- } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
- s_act_pdcycles += max(zero, timestamp - pdn_cycle);
- if (memSpec.memArchSpec.dll == false) {
- pup_act_cycles += memSpec.memTimingSpec.XP;
- latest_act_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RCD);
- } else {
- pup_act_cycles += memSpec.memTimingSpec.XPDLL -
- memSpec.memTimingSpec.RCD;
- latest_act_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XPDLL -
- (2 * memSpec.memTimingSpec.RCD));
- }
- } 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;
- bankstate = last_states;
- for (auto& a : last_states) {
- num_active_banks += static_cast<unsigned int>(a);
- }
- first_act_cycle = timestamp;
+ handlePupAct(timestamp);
} else if (type == MemCommand::PUP_PRE) {
- // If command is power-up in the precharged mode - check the power-down
- // exit-mode employed (fast or slow), update the number of power-down
- // and power-up cycles and the latest and last pre cycle.
- if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
- f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
- pup_pre_cycles += memSpec.memTimingSpec.XP;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
- } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
- s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
- if (memSpec.memArchSpec.dll == false) {
- pup_pre_cycles += memSpec.memTimingSpec.XP;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XP - memSpec.memTimingSpec.RP);
- } else {
- pup_pre_cycles += memSpec.memTimingSpec.XPDLL -
- memSpec.memTimingSpec.RCD;
- latest_pre_cycle = max(timestamp, timestamp +
- 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) {
- cerr << "Incorrect use of Precharged Power-Up!" << endl;
- }
- mem_state = 0;
- num_active_banks = 0;
- last_pre_cycle = timestamp;
+ handlePupPre(timestamp);
} else if (type == MemCommand::SREN) {
- // If command is self-refresh - update number of self-refreshes,
- // set memory state to SREF, update precharge and idle precharge
- // cycles and set the self-refresh cycle.
- printWarningIfActive("One or more banks are active! SREF requires all banks to be precharged.", type, timestamp, bank);
- numberofsrefs++;
- sref_cycle = timestamp;
- precycles += max(zero, timestamp - last_pre_cycle);
- idle_pre_update(memSpec, timestamp, latest_pre_cycle);
- mem_state = CommandAnalysis::MS_SREF;
+ handleSREn(bank, timestamp);
} else if (type == MemCommand::SREX) {
- // If command is self-refresh exit - update the number of self-refresh
- // clock cycles, number of active and precharged auto-refresh clock
- // cycles during self-refresh and self-refresh exit based on the number
- // of cycles in the self-refresh mode and auto-refresh duration (RFC).
- // Set the last and latest precharge cycle accordingly and set the
- // memory state to 0.
- if (mem_state != CommandAnalysis::MS_SREF) {
- cerr << "Incorrect use of Self-Refresh Power-Up!" << endl;
- }
- if (max(zero, timestamp - sref_cycle) >= memSpec.memTimingSpec.RFC) {
- sref_cycles += max(zero, timestamp - sref_cycle
- - memSpec.memTimingSpec.RFC);
- sref_ref_act_cycles += memSpec.memTimingSpec.RFC -
- memSpec.memTimingSpec.RP;
- sref_ref_pre_cycles += memSpec.memTimingSpec.RP;
- last_pre_cycle = timestamp;
- if (memSpec.memArchSpec.dll == false) {
- spup_cycles += memSpec.memTimingSpec.XS;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XS - memSpec.memTimingSpec.RP);
- } else {
- spup_cycles += memSpec.memTimingSpec.XSDLL -
- memSpec.memTimingSpec.RCD;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD
- - memSpec.memTimingSpec.RP);
- }
- } else {
- int64_t sref_diff = memSpec.memTimingSpec.RFC - memSpec.memTimingSpec.RP;
- int64_t sref_pre = max(zero, timestamp - sref_cycle - sref_diff);
- int64_t spup_pre = memSpec.memTimingSpec.RP - sref_pre;
- int64_t sref_act = max(zero, timestamp - sref_cycle);
- int64_t spup_act = memSpec.memTimingSpec.RFC - sref_act;
-
- if (max(zero, timestamp - sref_cycle) >= sref_diff) {
- sref_ref_act_cycles += sref_diff;
- sref_ref_pre_cycles += sref_pre;
- spup_ref_pre_cycles += spup_pre;
- last_pre_cycle = timestamp + spup_pre;
- if (memSpec.memArchSpec.dll == false) {
- spup_cycles += memSpec.memTimingSpec.XS - spup_pre;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XS - spup_pre -
- memSpec.memTimingSpec.RP);
- } else {
- spup_cycles += memSpec.memTimingSpec.XSDLL -
- memSpec.memTimingSpec.RCD - spup_pre;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
- spup_pre - memSpec.memTimingSpec.RP);
- }
- } else {
- sref_ref_act_cycles += sref_act;
- spup_ref_act_cycles += spup_act;
- spup_ref_pre_cycles += memSpec.memTimingSpec.RP;
- last_pre_cycle = timestamp + spup_act + memSpec.memTimingSpec.RP;
- if (memSpec.memArchSpec.dll == false) {
- spup_cycles += memSpec.memTimingSpec.XS - spup_act -
- memSpec.memTimingSpec.RP;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XS - spup_act -
- (2 * memSpec.memTimingSpec.RP));
- } else {
- spup_cycles += memSpec.memTimingSpec.XSDLL -
- memSpec.memTimingSpec.RCD - spup_act -
- memSpec.memTimingSpec.RP;
- latest_pre_cycle = max(timestamp, timestamp +
- memSpec.memTimingSpec.XSDLL - memSpec.memTimingSpec.RCD -
- spup_act - (2 * memSpec.memTimingSpec.RP));
- }
- }
- }
- mem_state = 0;
- num_active_banks = 0;
+ handleSREx(bank, timestamp);
} 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 (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 (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) {
- f_act_pdcycles += max(zero, timestamp - pdn_cycle);
- } else if (mem_state == CommandAnalysis::MS_PDN_S_ACT) {
- s_act_pdcycles += max(zero, timestamp - pdn_cycle);
- } else if (mem_state == CommandAnalysis::MS_PDN_F_PRE) {
- f_pre_pdcycles += max(zero, timestamp - pdn_cycle);
- } else if (mem_state == CommandAnalysis::MS_PDN_S_PRE) {
- s_pre_pdcycles += max(zero, timestamp - pdn_cycle);
- } else if (mem_state == CommandAnalysis::MS_SREF) {
- sref_cycles += max(zero, timestamp - sref_cycle);
- }
+ handleNopEnd(timestamp);
} else {
printWarning("Unknown command given, exiting.", type, timestamp, bank);
exit(-1);
}
}
-} // CommandAnalysis::evaluate
+} // CommandAnalysis::evaluateCommands
// To update idle period information whenever active cycles may be idle
-void CommandAnalysis::idle_act_update(const MemorySpecification& memSpec,
- int64_t latest_read_cycle, int64_t latest_write_cycle,
+void CommandAnalysis::idle_act_update(int64_t latest_read_cycle, int64_t latest_write_cycle,
int64_t latest_act_cycle, int64_t timestamp)
{
if (latest_read_cycle >= 0) {
- end_read_op = latest_read_cycle + timeToCompletion(memSpec,
- MemCommand::RD) - 1;
+ end_read_op = latest_read_cycle + timeToCompletion(MemCommand::RD) - 1;
}
if (latest_write_cycle >= 0) {
- end_write_op = latest_write_cycle + timeToCompletion(memSpec,
- MemCommand::WR) - 1;
+ end_write_op = latest_write_cycle + timeToCompletion(MemCommand::WR) - 1;
}
if (latest_act_cycle >= 0) {
- end_act_op = latest_act_cycle + timeToCompletion(memSpec,
- MemCommand::ACT) - 1;
+ end_act_op = latest_act_cycle + timeToCompletion(MemCommand::ACT) - 1;
}
idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op),
@@ -576,8 +282,7 @@ void CommandAnalysis::idle_act_update(const MemorySpecification& memSpec,
} // CommandAnalysis::idle_act_update
// To update idle period information whenever precharged cycles may be idle
-void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
- int64_t timestamp, int64_t latest_pre_cycle)
+void CommandAnalysis::idle_pre_update(int64_t timestamp, int64_t latest_pre_cycle)
{
if (latest_pre_cycle > 0) {
idlecycles_pre += max(zero, timestamp - latest_pre_cycle -
@@ -587,30 +292,3 @@ void CommandAnalysis::idle_pre_update(const MemorySpecification& memSpec,
}
}
-void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank)
-{
- if (num_active_banks != 0) {
- printWarning(warning, type, timestamp, bank);
- }
-}
-
-void CommandAnalysis::printWarningIfNotActive(const string& warning, int type, int64_t timestamp, int bank)
-{
- 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);
- }
-}
-
-void CommandAnalysis::printWarning(const string& warning, int type, int64_t timestamp, int bank)
-{
- cerr << "WARNING: " << warning << endl;
- cerr << "Command: " << type << ", Timestamp: " << timestamp <<
- ", Bank: " << bank << endl;
-}
diff --git a/ext/drampower/src/CommandAnalysis.h b/ext/drampower/src/CommandAnalysis.h
index 15261fb2f..6161e687b 100644
--- a/ext/drampower/src/CommandAnalysis.h
+++ b/ext/drampower/src/CommandAnalysis.h
@@ -31,7 +31,12 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
+ * Authors: Karthik Chandrasekar
+ * Matthias Jung
+ * Omar Naji
+ * Subash Kannoth
+ * Éder F. Zulian
+ * Felipe S. Prado
*
*/
@@ -54,27 +59,30 @@ class CommandAnalysis {
public:
// Power-Down and Self-refresh related memory states
enum memstate {
- MS_PDN_F_ACT = 10, MS_PDN_S_ACT = 11, MS_PDN_F_PRE = 12,
+ MS_NOT_IN_PD = 0, MS_PDN_F_ACT = 10, MS_PDN_S_ACT = 11, MS_PDN_F_PRE = 12,
MS_PDN_S_PRE = 13, MS_SREF = 14
};
// Returns number of reads, writes, acts, pres and refs in the trace
- CommandAnalysis(const int64_t nbrofBanks);
-
- // Number of activate commands
- int64_t numberofacts;
- // Number of precharge commands
- int64_t numberofpres;
- // Number of reads commands
- int64_t numberofreads;
- // Number of writes commands
- int64_t numberofwrites;
+ CommandAnalysis(const MemorySpecification& memSpec);
+
+ // Number of activate commands per bank
+ std::vector<int64_t> numberofactsBanks;
+ // Number of precharge commands per bank
+ std::vector<int64_t> numberofpresBanks;
+ // Number of reads commands per bank
+ std::vector<int64_t> numberofreadsBanks;
+ // Number of writes commands per bank
+ std::vector<int64_t> numberofwritesBanks;
// Number of refresh commands
int64_t numberofrefs;
+ // Number of bankwise refresh commands
+ std::vector<int64_t> numberofrefbBanks;
// Number of precharge cycles
int64_t precycles;
// Number of active cycles
int64_t actcycles;
+ std::vector<int64_t> actcyclesBanks;
// Number of Idle cycles in the active state
int64_t idlecycles_act;
// Number of Idle cycles in the precharge state
@@ -97,7 +105,8 @@ class CommandAnalysis {
int64_t f_pre_pdcycles;
// Number of clock cycles in slow-exit precharged power-down mode
int64_t s_pre_pdcycles;
- // Number of clock cycles in self-refresh mode
+ // Number of clock cycles in self-refresh mode (excludes the initial
+ // auto-refresh). During this time the current drawn is IDD6.
int64_t sref_cycles;
// Number of clock cycles in activate power-up mode
int64_t pup_act_cycles;
@@ -106,10 +115,15 @@ class CommandAnalysis {
// Number of clock cycles in self-refresh power-up mode
int64_t spup_cycles;
- // Number of active auto-refresh cycles in self-refresh mode
+ // Number of active cycles for the initial auto-refresh when entering
+ // self-refresh mode.
int64_t sref_ref_act_cycles;
+ // Number of active auto-refresh cycles in self-refresh mode already used to calculate the energy of the previous windows
+ int64_t sref_ref_act_cycles_window;
// Number of precharged auto-refresh cycles in self-refresh mode
int64_t sref_ref_pre_cycles;
+ // Number of precharged auto-refresh cycles in self-refresh mode already used to calculate the energy of the previous window
+ int64_t sref_ref_pre_cycles_window;
// Number of active auto-refresh cycles during self-refresh exit
int64_t spup_ref_act_cycles;
// Number of precharged auto-refresh cycles during self-refresh exit
@@ -122,11 +136,19 @@ class CommandAnalysis {
void clear();
// To identify auto-precharges
- void getCommands(const MemorySpecification& memSpec,
- std::vector<MemCommand>& list,
- bool lastupdate);
+ void getCommands(std::vector<MemCommand>& list,
+ bool lastupdate,
+ int64_t timestamp = 0);
private:
+ MemorySpecification memSpec;
+
+ // Possible bank states are precharged or active
+ enum BankState {
+ BANK_PRECHARGED = 0,
+ BANK_ACTIVE
+ };
+
int64_t zero;
// Cached last read command from the file
std::vector<MemCommand> cached_cmd;
@@ -134,11 +156,14 @@ class CommandAnalysis {
// Stores the memory commands for analysis
std::vector<MemCommand> cmd_list;
+ //Stores the memory commands for the next window
+ std::vector<MemCommand> next_window_cmd_list;
+
// To save states of the different banks, before entering active
// power-down mode (slow/fast-exit).
- std::vector<int> last_states;
+ std::vector<BankState> last_bank_state;
// Bank state vector
- std::vector<int> bankstate;
+ std::vector<BankState> bank_state;
std::vector<int64_t> activation_cycle;
// To keep track of the last ACT cycle
@@ -160,43 +185,68 @@ class CommandAnalysis {
// Clock cycle when self-refresh was issued
int64_t sref_cycle;
+ // Latest Self-Refresh clock cycle used to calculate the energy of the previous window
+ int64_t sref_cycle_window;
+
// Clock cycle when the latest power-down was issued
int64_t pdn_cycle;
// Memory State
unsigned mem_state;
- unsigned num_active_banks;
+
+ int64_t num_banks;
// Clock cycle of first activate command when memory state changes to ACT
int64_t first_act_cycle;
+ std::vector<int64_t> first_act_cycle_banks;
// Clock cycle of last precharge command when memory state changes to PRE
int64_t last_pre_cycle;
// To perform timing analysis of a given set of commands and update command counters
- void evaluate(const MemorySpecification& memSpec,
- std::vector<MemCommand>& cmd_list);
+ void evaluateCommands(std::vector<MemCommand>& cmd_list);
+
+ // Handlers for commands that are getting processed
+ void handleAct( unsigned bank, int64_t timestamp);
+ void handleRd( unsigned bank, int64_t timestamp);
+ void handleWr( unsigned bank, int64_t timestamp);
+ void handleRef( unsigned bank, int64_t timestamp);
+ void handleRefB(unsigned bank, int64_t timestamp);
+ void handlePre( unsigned bank, int64_t timestamp);
+ void handlePreA( unsigned bank, int64_t timestamp);
+ void handlePdnFAct(unsigned bank, int64_t timestamp);
+ void handlePdnSAct(unsigned bank, int64_t timestamp);
+ void handlePdnFPre(unsigned bank, int64_t timestamp);
+ void handlePdnSPre(unsigned bank, int64_t timestamp);
+ void handlePupAct( int64_t timestamp);
+ void handlePupPre( int64_t timestamp);
+ void handleSREn( unsigned bank, int64_t timestamp);
+ void handleSREx( unsigned bank, int64_t timestamp);
+ void handleNopEnd( int64_t timestamp);
// To calculate time of completion of any issued command
- int64_t timeToCompletion(const MemorySpecification& memSpec,
- MemCommand::cmds type);
+ int64_t timeToCompletion(MemCommand::cmds type);
// To update idle period information whenever active cycles may be idle
- void idle_act_update(const MemorySpecification& memSpec,
- int64_t latest_read_cycle,
+ void idle_act_update(int64_t latest_read_cycle,
int64_t latest_write_cycle,
int64_t latest_act_cycle,
int64_t timestamp);
// To update idle period information whenever precharged cycles may be idle
- void idle_pre_update(const MemorySpecification& memSpec,
- int64_t timestamp,
+ void idle_pre_update(int64_t timestamp,
int64_t latest_pre_cycle);
- void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, int bank);
- void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, int bank);
- void printWarningIfPoweredDown(const std::string& warning, int type, int64_t timestamp, int bank);
- void printWarning(const std::string& warning, int type, int64_t timestamp, int bank);
+ // Returns the number of active banks according to the bank_state vector.
+ unsigned get_num_active_banks(void);
+ unsigned nActiveBanks(void);
+
+ bool isPrecharged(unsigned bank);
+
+ void printWarningIfActive(const std::string& warning, int type, int64_t timestamp, unsigned bank);
+ void printWarningIfNotActive(const std::string& warning, int type, int64_t timestamp, unsigned bank);
+ void printWarningIfPoweredDown(const std::string& warning, int type, int64_t timestamp, unsigned bank);
+ void printWarning(const std::string& warning, int type, int64_t timestamp, unsigned bank);
};
}
#endif // ifndef COMMAND_TIMINGS_H
diff --git a/ext/drampower/src/MemBankWiseParams.cc b/ext/drampower/src/MemBankWiseParams.cc
new file mode 100644
index 000000000..c13281688
--- /dev/null
+++ b/ext/drampower/src/MemBankWiseParams.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2012-2014, TU Delft
+ * Copyright (c) 2012-2014, TU Eindhoven
+ * Copyright (c) 2012-2016, TU Kaiserslautern
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Subash Kannoth, Matthias Jung, Éder F. Zulian
+ *
+ */
+
+#include "MemBankWiseParams.h"
+
+using namespace Data;
+/**
+ * Sets the default bankwise configurations.
+ */
+MemBankWiseParams::MemBankWiseParams():
+ bwPowerFactRho(100),
+ bwPowerFactSigma(100),
+ bwMode(false),
+ flgPASR(false)
+{
+}
+/**
+ * Sets all the bankwise parameters required in bankwise mode
+ */
+MemBankWiseParams::MemBankWiseParams(int64_t factRho, int64_t factSigma,
+ bool hasPASR, int64_t pasrMode,
+ bool opMode, unsigned nbrofBanks)
+{
+
+ bwPowerFactRho = factRho;
+ bwPowerFactSigma = factSigma;
+ bwMode = opMode;
+ flgPASR = hasPASR;
+ ///////////////////////////////////////////////////////////
+ // Activate banks for self refresh based on the PASR mode
+ // ACTIVE - X
+ // NOT ACTIVE - 0
+ ///////////////////////////////////////////////////////////
+ switch(pasrMode){
+
+ case(PASR_0):{
+ // PASR MODE 0
+ // FULL ARRAY
+ // |X X X X |
+ // |X X X X |
+ activeBanks.resize(nbrofBanks);
+ std::iota(activeBanks.begin(), activeBanks.end(), 0);
+ break;
+ }
+ case(PASR_1):{
+ // PASR MODE 1
+ // (1/2) ARRAY
+ // |X X X X |
+ // |0 0 0 0 |
+ activeBanks.resize(nbrofBanks - 4);
+ std::iota(activeBanks.begin(), activeBanks.end(), 0);
+ break;
+ }
+ case(PASR_2):{
+ // PASR MODE 2
+ // (1/4) ARRAY
+ // |X X 0 0 |
+ // |0 0 0 0 |
+ activeBanks.resize(nbrofBanks - 6);
+ std::iota(activeBanks.begin(), activeBanks.end(), 0);
+ break;
+ }
+ case(PASR_3):{
+ // PASR MODE 3
+ // (1/8) ARRAY
+ // |X 0 0 0 |
+ // |0 0 0 0 |
+ activeBanks.resize(nbrofBanks - 7);
+ std::iota(activeBanks.begin(), activeBanks.end(), 0);
+ break;
+ }
+ case(PASR_4):{
+ // PASR MODE 4
+ // (3/4) ARRAY
+ // |0 0 X X |
+ // |X X X X |
+ activeBanks.resize(nbrofBanks - 2);
+ std::iota(activeBanks.begin(), activeBanks.end(), 2);
+ break;
+ }
+ case(PASR_5):{
+ // PASR MODE 5
+ // (1/2) ARRAY
+ // |0 0 0 0 |
+ // |X X X X |
+ activeBanks.resize(nbrofBanks - 4);
+ std::iota(activeBanks.begin(), activeBanks.end(), 4);
+ break;
+ }
+ case(PASR_6):{
+ // PASR MODE 6
+ // (1/4) ARRAY
+ // |0 0 0 0 |
+ // |0 0 X X |
+ activeBanks.resize(nbrofBanks - 6);
+ std::iota(activeBanks.begin(), activeBanks.end(), 6);
+ break;
+ }
+ case(PASR_7):{
+ // PASR MODE 7
+ // (1/8) ARRAY
+ // |0 0 0 0 |
+ // |0 0 0 X |
+ activeBanks.resize(nbrofBanks - 7);
+ std::iota(activeBanks.begin(), activeBanks.end(), 7);
+ break;
+ }
+ default:{
+ // PASR MODE 0
+ // FULL ARRAY
+ // |X X X X |
+ // |X X X X |
+ activeBanks.resize(nbrofBanks);
+ std::iota(activeBanks.begin(), activeBanks.end(), 0);
+ break;
+ }
+ }
+}
+
+/**
+ * Returns true if the given bank is active under the current PASR mode.
+ */
+bool MemBankWiseParams::isBankActiveInPasr(const unsigned bankIdx) const
+{
+ return (std::find(activeBanks.begin(), activeBanks.end(), bankIdx)
+ != activeBanks.end());
+}
diff --git a/ext/drampower/src/MemBankWiseParams.h b/ext/drampower/src/MemBankWiseParams.h
new file mode 100644
index 000000000..0cc98fb46
--- /dev/null
+++ b/ext/drampower/src/MemBankWiseParams.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2012-2014, TU Delft
+ * Copyright (c) 2012-2014, TU Eindhoven
+ * Copyright (c) 2012-2016, TU Kaiserslautern
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Authors: Subash Kannoth, Matthias Jung, Eder Zulian
+ *
+ */
+#ifndef MEMBANKWISEPARAMS_H
+#define MEMBANKWISEPARAMS_H
+
+#include <stdint.h>
+#include <vector>
+#include <algorithm>
+#include <numeric>
+
+namespace Data {
+ class MemBankWiseParams {
+ public:
+ // Set of possible PASR modes
+ enum pasrModes{
+ PASR_0,
+ PASR_1,
+ PASR_2,
+ PASR_3,
+ PASR_4,
+ PASR_5,
+ PASR_6,
+ PASR_7
+ };
+ // List of active banks under the specified PASR mode
+ std::vector<unsigned> activeBanks;
+ // ACT Standby power factor
+ int64_t bwPowerFactRho;
+ // Self-Refresh power factor( true : Bankwise mode)
+ int64_t bwPowerFactSigma;
+ // Bankwise or Normal mode
+ bool bwMode;
+ // Wherther PASR is enabled ( true : enabled )
+ bool flgPASR;
+ //Default constructor
+ MemBankWiseParams();
+ MemBankWiseParams(int64_t factRho, int64_t factSigma,
+ bool hasPASR, int64_t pasrMode,
+ bool opMode, unsigned nbrofBanks);
+
+ bool isBankActiveInPasr(const unsigned bankIdx) const;
+ };
+}
+
+#endif // MEMBANKWISEPARAMS_H
diff --git a/ext/drampower/src/MemCommand.h b/ext/drampower/src/MemCommand.h
index 9eb751088..3d7b70b5f 100644
--- a/ext/drampower/src/MemCommand.h
+++ b/ext/drampower/src/MemCommand.h
@@ -53,19 +53,20 @@ class MemCommand {
* 3. WR - Write
* 4. PRE - Explicit Precharge per bank
* 5. REF - Refresh all banks
- * 6. END - To indicate end of trace
- * 7. RDA - Read with auto-precharge
- * 8. WRA - Write with auto-precharge
- * 9. PREA - Precharge all banks
- * 10. PDN_F_PRE - Precharge Power-down Entry command (Fast-Exit)
- * 11. PDN_S_PRE - Precharge Power-down Entry command (Slow-Exit)
- * 12. PDN_F_ACT - Active Power-down Entry command (Fast-Exit)
- * 13. PDN_S_ACT - Active Power-down Entry command (Slow-Exit)
- * 14. PUP_PRE - Precharge Power-down Exit
- * 15. PUP_ACT - Active Power-down Exit
- * 16. SREN - Self-Refresh Entry command
- * 17. SREX - Self-refresh Exit
- * 18. NOP - To indicate end of trace
+ * 6 REFB- Refresh a particular bank
+ * 7. END - To indicate end of trace
+ * 8. RDA - Read with auto-precharge
+ * 9. WRA - Write with auto-precharge
+ * 10. PREA - Precharge all banks
+ * 11. PDN_F_PRE - Precharge Power-down Entry command (Fast-Exit)
+ * 12. PDN_S_PRE - Precharge Power-down Entry command (Slow-Exit)
+ * 13. PDN_F_ACT - Active Power-down Entry command (Fast-Exit)
+ * 14. PDN_S_ACT - Active Power-down Entry command (Slow-Exit)
+ * 15. PUP_PRE - Precharge Power-down Exit
+ * 16. PUP_ACT - Active Power-down Exit
+ * 17. SREN - Self-Refresh Entry command
+ * 18. SREX - Self-refresh Exit
+ * 19. NOP - To indicate end of trace
*/
enum cmds {
@@ -74,20 +75,21 @@ class MemCommand {
WR = 2,
PRE = 3,
REF = 4,
- END = 5,
- RDA = 6,
- WRA = 7,
- PREA = 8,
- PDN_F_PRE = 9,
- PDN_S_PRE = 10,
- PDN_F_ACT = 11,
- PDN_S_ACT = 12,
- PUP_PRE = 13,
- PUP_ACT = 14,
- SREN = 15,
- SREX = 16,
- NOP = 17,
- UNINITIALIZED = 18
+ REFB = 5,
+ END = 6,
+ RDA = 7,
+ WRA = 8,
+ PREA = 9,
+ PDN_F_PRE = 10,
+ PDN_S_PRE = 11,
+ PDN_F_ACT = 12,
+ PDN_S_ACT = 13,
+ PUP_PRE = 14,
+ PUP_ACT = 15,
+ SREN = 16,
+ SREX = 17,
+ NOP = 18,
+ UNINITIALIZED = 19
};
// MemCommand();
@@ -136,7 +138,7 @@ class MemCommand {
}
}
- static const unsigned int nCommands = 19;
+ static const unsigned int nCommands = 20;
static std::string* getCommandTypeStrings()
{
@@ -145,6 +147,7 @@ class MemCommand {
"WR",
"PRE",
"REF",
+ "REFB",
"END",
"RDA",
"WRA",
diff --git a/ext/drampower/src/MemPowerSpec.cc b/ext/drampower/src/MemPowerSpec.cc
index 3fbc53992..2f7011c0e 100644
--- a/ext/drampower/src/MemPowerSpec.cc
+++ b/ext/drampower/src/MemPowerSpec.cc
@@ -60,6 +60,7 @@ MemPowerSpec::MemPowerSpec() :
idd4w2(0.0),
idd5(0.0),
idd52(0.0),
+ idd5B(0.0),
idd6(0.0),
idd62(0.0),
vdd(0.0),
@@ -94,6 +95,7 @@ void MemPowerSpec::processParameters()
idd4w2 = getParamValWithDefault("idd4w2", 0.0);
idd5 = getParamValWithDefault("idd5", 0.0);
idd52 = getParamValWithDefault("idd52", 0.0);
+ idd5B = getParamValWithDefault("idd5B", 0.0);
idd6 = getParamValWithDefault("idd6", 0.0);
idd62 = getParamValWithDefault("idd62", 0.0);
vdd = getParamValWithDefault("vdd", 0.0);
diff --git a/ext/drampower/src/MemPowerSpec.h b/ext/drampower/src/MemPowerSpec.h
index f6958820d..c5243dcdf 100644
--- a/ext/drampower/src/MemPowerSpec.h
+++ b/ext/drampower/src/MemPowerSpec.h
@@ -63,6 +63,7 @@ class MemPowerSpec : public virtual Parametrisable {
double idd4w2;
double idd5;
double idd52;
+ double idd5B;
double idd6;
double idd62;
double vdd;
diff --git a/ext/drampower/src/MemTimingSpec.cc b/ext/drampower/src/MemTimingSpec.cc
index cf18c5f7b..54b07e3bc 100644
--- a/ext/drampower/src/MemTimingSpec.cc
+++ b/ext/drampower/src/MemTimingSpec.cc
@@ -58,6 +58,7 @@ MemTimingSpec::MemTimingSpec() :
RL(0),
RP(0),
RFC(0),
+ REFB(0),
RAS(0),
WL(0),
AL(0),
@@ -94,6 +95,7 @@ void MemTimingSpec::processParameters()
RL = getParamValWithDefault("RL", 0);
RP = getParamValWithDefault("RP", 0);
RFC = getParamValWithDefault("RFC", 0);
+ REFB = getParamValWithDefault("REFB", 0);
RAS = getParamValWithDefault("RAS", 0);
WL = getParamValWithDefault("WL", 0);
AL = getParamValWithDefault("AL", 0);
diff --git a/ext/drampower/src/MemTimingSpec.h b/ext/drampower/src/MemTimingSpec.h
index 104bf5c71..2413177b0 100644
--- a/ext/drampower/src/MemTimingSpec.h
+++ b/ext/drampower/src/MemTimingSpec.h
@@ -63,6 +63,7 @@ class MemTimingSpec : public virtual Parametrisable {
int64_t RL;
int64_t RP;
int64_t RFC;
+ int64_t REFB;
int64_t RAS;
int64_t WL;
int64_t AL;
diff --git a/ext/drampower/src/MemoryPowerModel.cc b/ext/drampower/src/MemoryPowerModel.cc
index e020830e6..5c3549c00 100644
--- a/ext/drampower/src/MemoryPowerModel.cc
+++ b/ext/drampower/src/MemoryPowerModel.cc
@@ -31,7 +31,12 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
+ * Authors: Karthik Chandrasekar
+ * Matthias Jung
+ * Omar Naji
+ * Subash Kannoth
+ * Éder F. Zulian
+ * Felipe S. Prado
*
*/
@@ -41,20 +46,55 @@
#include <cmath> // For pow
#include <iostream> // fmtflags
-
+#include <algorithm>
using namespace std;
using namespace Data;
+MemoryPowerModel::MemoryPowerModel()
+{
+ total_cycles = 0;
+ energy.total_energy = 0;
+}
+
// Calculate energy and average power consumption for the given command trace
void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
const CommandAnalysis& c,
- int term)
+ int term,
+ const MemBankWiseParams& bwPowerParams)
{
const MemTimingSpec& t = memSpec.memTimingSpec;
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
const MemPowerSpec& mps = memSpec.memPowerSpec;
+ const int64_t nbrofBanks = memSpec.memArchSpec.nbrOfBanks;
+
+ energy.act_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.pre_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.read_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.write_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.ref_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.refb_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.act_stdby_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.pre_stdby_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.idle_energy_act_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.idle_energy_pre_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.f_act_pd_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.f_pre_pd_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.s_act_pd_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.s_pre_pd_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.ref_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.sref_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.sref_ref_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.sref_ref_act_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.sref_ref_pre_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.spup_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.spup_ref_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.spup_ref_act_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.spup_ref_pre_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.pup_act_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.pup_pre_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
+ energy.total_energy_banks.assign(static_cast<size_t>(nbrofBanks), 0.0);
energy.act_energy = 0.0;
energy.pre_energy = 0.0;
@@ -65,7 +105,7 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
energy.pre_stdby_energy = 0.0;
energy.idle_energy_act = 0.0;
energy.idle_energy_pre = 0.0;
- energy.total_energy = 0.0;
+ energy.window_energy = 0.0;
energy.f_act_pd_energy = 0.0;
energy.f_pre_pd_energy = 0.0;
energy.s_act_pd_energy = 0.0;
@@ -106,13 +146,13 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
double ddrPeriod = t.clkPeriod / static_cast<double>(memArchSpec.dataRate);
// Read IO power is consumed by each DQ (data) and DQS (data strobe) pin
- energy.read_io_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
+ energy.read_io_energy = calcIoTermEnergy(sum(c.numberofreadsBanks) * memArchSpec.burstLength,
ddrPeriod,
power.IO_power,
dqPlusDqsBits);
// Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM
- energy.write_term_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
+ energy.write_term_energy = calcIoTermEnergy(sum(c.numberofwritesBanks) * memArchSpec.burstLength,
ddrPeriod,
power.WR_ODT_power,
dqPlusDqsPlusMaskBits);
@@ -120,14 +160,14 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
if (memArchSpec.nbrOfRanks > 1) {
// Termination power consumed in the idle rank during reads on the active
// rank by each DQ (data) and DQS (data strobe) pin.
- energy.read_oterm_energy = calcIoTermEnergy(c.numberofreads * memArchSpec.burstLength,
+ energy.read_oterm_energy = calcIoTermEnergy(sum(c.numberofreadsBanks) * memArchSpec.burstLength,
ddrPeriod,
power.TermRD_power,
dqPlusDqsBits);
// Termination power consumed in the idle rank during writes on the active
// rank by each DQ (data), DQS (data strobe) and DM (data mask) pin.
- energy.write_oterm_energy = calcIoTermEnergy(c.numberofwrites * memArchSpec.burstLength,
+ energy.write_oterm_energy = calcIoTermEnergy(sum(c.numberofwritesBanks) * memArchSpec.burstLength,
ddrPeriod,
power.TermWR_power,
dqPlusDqsPlusMaskBits);
@@ -138,7 +178,7 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
+ energy.read_oterm_energy + energy.write_oterm_energy;
}
- total_cycles = c.actcycles + c.precycles +
+ window_cycles = c.actcycles + c.precycles +
c.f_act_pdcycles + c.f_pre_pdcycles +
c.s_act_pdcycles + c.s_pre_pdcycles + c.sref_cycles
+ c.sref_ref_act_cycles + c.sref_ref_pre_cycles +
@@ -146,13 +186,69 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod);
- energy.act_energy = vdd0Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd0 - mps.idd3n);
- energy.pre_energy = vdd0Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
- energy.read_energy = vdd0Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r - mps.idd3n);
- energy.write_energy = vdd0Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w - mps.idd3n);
+ energy.act_energy = vdd0Domain.calcTivEnergy(sum(c.numberofactsBanks) * t.RAS , mps.idd0 - mps.idd3n);
+ energy.pre_energy = vdd0Domain.calcTivEnergy(sum(c.numberofpresBanks) * (t.RC - t.RAS) , mps.idd0 - mps.idd2n);
+ energy.read_energy = vdd0Domain.calcTivEnergy(sum(c.numberofreadsBanks) * burstCc , mps.idd4r - mps.idd3n);
+ energy.write_energy = vdd0Domain.calcTivEnergy(sum(c.numberofwritesBanks) * burstCc , mps.idd4w - mps.idd3n);
energy.ref_energy = vdd0Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd5 - mps.idd3n);
energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(c.precycles, mps.idd2n);
energy.act_stdby_energy = vdd0Domain.calcTivEnergy(c.actcycles, mps.idd3n);
+
+ // Using the number of cycles that at least one bank is active here
+ // But the current iddrho is less than idd3n
+ double iddrho = (static_cast<double>(bwPowerParams.bwPowerFactRho) / 100.0) * (mps.idd3n - mps.idd2n) + mps.idd2n;
+ double esharedActStdby = vdd0Domain.calcTivEnergy(c.actcycles, iddrho);
+ // Fixed componenent for PASR
+ double iddsigma = (static_cast<double>(bwPowerParams.bwPowerFactSigma) / 100.0) * mps.idd6;
+ double esharedPASR = vdd0Domain.calcTivEnergy(c.sref_cycles, iddsigma);
+ // ione is Active background current for a single bank. When a single bank is Active
+ //,all the other remainig (B-1) banks will consume a current of iddrho (based on factor Rho)
+ // So to derrive ione we add (B-1)*iddrho to the idd3n and distribute it to each banks.
+ double ione = (mps.idd3n + (iddrho * (static_cast<double>(nbrofBanks - 1)))) / (static_cast<double>(nbrofBanks));
+ // If memory specification does not provide bank wise refresh current,
+ // approximate it to single bank background current removed from
+ // single bank active current
+ double idd5Blocal = (mps.idd5B == 0.0) ? (mps.idd0 - ione) :(mps.idd5B);
+ // if memory specification does not provide the REFB timing approximate it
+ // to time of ACT + PRE
+ int64_t tRefBlocal = (t.REFB == 0) ? (t.RAS + t.RP) : (t.REFB);
+
+ //Distribution of energy componets to each banks
+ for (unsigned i = 0; i < nbrofBanks; i++) {
+ energy.act_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofactsBanks[i] * t.RAS, mps.idd0 - ione);
+ energy.pre_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofpresBanks[i] * (t.RP), mps.idd0 - ione);
+ energy.read_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofreadsBanks[i] * burstCc, mps.idd4r - mps.idd3n);
+ energy.write_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofwritesBanks[i] * burstCc, mps.idd4w - mps.idd3n);
+ energy.ref_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofrefs * t.RFC, mps.idd5 - mps.idd3n) / static_cast<double>(nbrofBanks);
+ energy.refb_energy_banks[i] = vdd0Domain.calcTivEnergy(c.numberofrefbBanks[i] * tRefBlocal, idd5Blocal);
+ energy.pre_stdby_energy_banks[i] = vdd0Domain.calcTivEnergy(c.precycles, mps.idd2n) / static_cast<double>(nbrofBanks);
+ energy.act_stdby_energy_banks[i] = vdd0Domain.calcTivEnergy(c.actcyclesBanks[i], (mps.idd3n - iddrho) / static_cast<double>(nbrofBanks))
+ + esharedActStdby / static_cast<double>(nbrofBanks);
+ energy.idle_energy_act_banks[i] = vdd0Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n) / static_cast<double>(nbrofBanks);
+ energy.idle_energy_pre_banks[i] = vdd0Domain.calcTivEnergy(c.idlecycles_pre, mps.idd2n) / static_cast<double>(nbrofBanks);
+ energy.f_act_pd_energy_banks[i] = vdd0Domain.calcTivEnergy(c.f_act_pdcycles, mps.idd3p1) / static_cast<double>(nbrofBanks);
+ energy.f_pre_pd_energy_banks[i] = vdd0Domain.calcTivEnergy(c.f_pre_pdcycles, mps.idd2p1) / static_cast<double>(nbrofBanks);
+ energy.s_act_pd_energy_banks[i] = vdd0Domain.calcTivEnergy(c.s_act_pdcycles, mps.idd3p0) / static_cast<double>(nbrofBanks);
+ energy.s_pre_pd_energy_banks[i] = vdd0Domain.calcTivEnergy(c.s_pre_pdcycles, mps.idd2p0) / static_cast<double>(nbrofBanks);
+
+ energy.sref_energy_banks[i] = engy_sref_banks(mps.idd6, mps.idd3n,
+ mps.idd5, mps.vdd,
+ static_cast<double>(c.sref_cycles), static_cast<double>(c.sref_ref_act_cycles),
+ static_cast<double>(c.sref_ref_pre_cycles), static_cast<double>(c.spup_ref_act_cycles),
+ static_cast<double>(c.spup_ref_pre_cycles), t.clkPeriod,esharedPASR,bwPowerParams,i,nbrofBanks
+ );
+ energy.sref_ref_act_energy_banks[i] = vdd0Domain.calcTivEnergy(c.sref_ref_act_cycles, mps.idd3p0) / static_cast<double>(nbrofBanks);
+ energy.sref_ref_pre_energy_banks[i] = vdd0Domain.calcTivEnergy(c.sref_ref_pre_cycles, mps.idd2p0) / static_cast<double>(nbrofBanks);
+ energy.sref_ref_energy_banks[i] = energy.sref_ref_act_energy_banks[i] + energy.sref_ref_pre_energy_banks[i] ;//
+
+ energy.spup_energy_banks[i] = vdd0Domain.calcTivEnergy(c.spup_cycles, mps.idd2n) / static_cast<double>(nbrofBanks);
+ energy.spup_ref_act_energy_banks[i] = vdd0Domain.calcTivEnergy(c.spup_ref_act_cycles, mps.idd3n) / static_cast<double>(nbrofBanks);//
+ energy.spup_ref_pre_energy_banks[i] = vdd0Domain.calcTivEnergy(c.spup_ref_pre_cycles, mps.idd2n) / static_cast<double>(nbrofBanks);
+ energy.spup_ref_energy_banks[i] = ( energy.spup_ref_act_energy + energy.spup_ref_pre_energy ) / static_cast<double>(nbrofBanks);
+ energy.pup_act_energy_banks[i] = vdd0Domain.calcTivEnergy(c.pup_act_cycles, mps.idd3n) / static_cast<double>(nbrofBanks);
+ energy.pup_pre_energy_banks[i] = vdd0Domain.calcTivEnergy(c.pup_pre_cycles, mps.idd2n) / static_cast<double>(nbrofBanks);
+ }
+
// Idle energy in the active standby clock cycles
energy.idle_energy_act = vdd0Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n);
// Idle energy in the precharge standby clock cycles
@@ -193,13 +289,14 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
if (memArchSpec.twoVoltageDomains) {
EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod);
- energy.act_energy += vdd2Domain.calcTivEnergy(c.numberofacts * t.RAS , mps.idd02 - mps.idd3n2);
- energy.pre_energy += vdd2Domain.calcTivEnergy(c.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
- energy.read_energy += vdd2Domain.calcTivEnergy(c.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2);
- energy.write_energy += vdd2Domain.calcTivEnergy(c.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2);
+ energy.act_energy += vdd2Domain.calcTivEnergy(sum(c.numberofactsBanks) * t.RAS , mps.idd02 - mps.idd3n2);
+ energy.pre_energy += vdd2Domain.calcTivEnergy(sum(c.numberofpresBanks) * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2);
+ energy.read_energy += vdd2Domain.calcTivEnergy(sum(c.numberofreadsBanks) * burstCc , mps.idd4r2 - mps.idd3n2);
+ energy.write_energy += vdd2Domain.calcTivEnergy(sum(c.numberofwritesBanks) * burstCc , mps.idd4w2 - mps.idd3n2);
energy.ref_energy += vdd2Domain.calcTivEnergy(c.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2);
energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(c.precycles, mps.idd2n2);
energy.act_stdby_energy += vdd2Domain.calcTivEnergy(c.actcycles, mps.idd3n2);
+
// Idle energy in the active standby clock cycles
energy.idle_energy_act += vdd2Domain.calcTivEnergy(c.idlecycles_act, mps.idd3n2);
// Idle energy in the precharge standby clock cycles
@@ -243,34 +340,71 @@ void MemoryPowerModel::power_calc(const MemorySpecification& memSpec,
// adding all energy components for the active rank and all background and idle
// energy components for both ranks (in a dual-rank system)
- energy.total_energy = energy.act_energy + energy.pre_energy + energy.read_energy +
- energy.write_energy + energy.ref_energy + energy.io_term_energy +
- static_cast<double>(memArchSpec.nbrOfRanks) * (energy.act_stdby_energy +
- energy.pre_stdby_energy + energy.sref_energy +
- energy.f_act_pd_energy + energy.f_pre_pd_energy + energy.s_act_pd_energy
- + energy.s_pre_pd_energy + energy.sref_ref_energy + energy.spup_ref_energy);
+
+ if (bwPowerParams.bwMode) {
+ // Calculate total energy per bank.
+ for (unsigned i = 0; i < nbrofBanks; i++) {
+ energy.total_energy_banks[i] = energy.act_energy_banks[i] + energy.pre_energy_banks[i] + energy.read_energy_banks[i]
+ + energy.ref_energy_banks[i] + energy.write_energy_banks[i] + energy.refb_energy_banks[i]
+ + static_cast<double>(memArchSpec.nbrOfRanks) * energy.act_stdby_energy_banks[i]
+ + energy.pre_stdby_energy_banks[i] + energy.f_pre_pd_energy_banks[i] + energy.s_act_pd_energy_banks[i]
+ + energy.s_pre_pd_energy_banks[i]+ energy.sref_ref_energy_banks[i] + energy.spup_ref_energy_banks[i];
+ }
+ // Calculate total energy for all banks.
+ energy.window_energy = sum(energy.total_energy_banks) + energy.io_term_energy;
+
+ } else {
+ energy.window_energy = energy.act_energy + energy.pre_energy + energy.read_energy + energy.write_energy
+ + energy.ref_energy + energy.io_term_energy + sum(energy.refb_energy_banks)
+ + static_cast<double>(memArchSpec.nbrOfRanks) * (energy.act_stdby_energy
+ + energy.pre_stdby_energy + energy.sref_energy + energy.f_act_pd_energy
+ + energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy
+ + energy.sref_ref_energy + energy.spup_ref_energy);
+ }
+
+ power.window_average_power = energy.window_energy / (static_cast<double>(window_cycles) * t.clkPeriod);
+
+ total_cycles += window_cycles;
+
+ energy.total_energy += energy.window_energy;
// Calculate the average power consumption
power.average_power = energy.total_energy / (static_cast<double>(total_cycles) * t.clkPeriod);
} // MemoryPowerModel::power_calc
-void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term, const CommandAnalysis& c) const
+void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term, const CommandAnalysis& c, bool bankwiseMode) const
{
const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec;
const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec;
const uint64_t nRanks = static_cast<uint64_t>(memArchSpec.nbrOfRanks);
const char eUnit[] = " pJ";
+ const int64_t nbrofBanks = memSpec.memArchSpec.nbrOfBanks;
+ double nRanksDouble = static_cast<double>(nRanks);
ios_base::fmtflags flags = cout.flags();
streamsize precision = cout.precision();
cout.precision(0);
- cout << "* Trace Details:" << fixed << endl
- << endl << "#ACT commands: " << c.numberofacts
- << endl << "#RD + #RDA commands: " << c.numberofreads
- << endl << "#WR + #WRA commands: " << c.numberofwrites
+
+ if (bankwiseMode) {
+ cout << endl << "* Bankwise Details:";
+ for (unsigned i = 0; i < nbrofBanks; i++) {
+ cout << endl << "## @ Bank " << i << fixed
+ << endl << " #ACT commands: " << c.numberofactsBanks[i]
+ << endl << " #RD + #RDA commands: " << c.numberofreadsBanks[i]
+ << endl << " #WR + #WRA commands: " << c.numberofwritesBanks[i]
+ << endl << " #PRE (+ PREA) commands: " << c.numberofpresBanks[i];
+ }
+ cout << endl;
+ }
+
+ cout << endl << "* Trace Details:" << fixed << endl
+ << endl << "#ACT commands: " << sum(c.numberofactsBanks)
+ << endl << "#RD + #RDA commands: " << sum(c.numberofreadsBanks)
+ << endl << "#WR + #WRA commands: " << sum(c.numberofwritesBanks)
/* #PRE commands (precharge all counts a number of #PRE commands equal to the number of active banks) */
- << endl << "#PRE (+ PREA) commands: " << c.numberofpres
+ << endl << "#PRE (+ PREA) commands: " << sum(c.numberofpresBanks)
<< endl << "#REF commands: " << c.numberofrefs
+ << endl << "#REFB commands: " << sum(c.numberofrefbBanks)
<< endl << "#Active Cycles: " << c.actcycles
<< endl << " #Active Idle Cycles: " << c.idlecycles_act
<< endl << " #Active Power-Up Cycles: " << c.pup_act_cycles
@@ -300,6 +434,38 @@ void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term,
<< endl << "Total Trace Length (clock cycles): " << total_cycles
<< endl << "----------------------------------------" << endl;
+ if (bankwiseMode) {
+ cout << endl << "* Bankwise Details:";
+ for (unsigned i = 0; i < nbrofBanks; i++) {
+ cout << endl << "## @ Bank " << i << fixed
+ << endl << " ACT Cmd Energy: " << energy.act_energy_banks[i] << eUnit
+ << endl << " PRE Cmd Energy: " << energy.pre_energy_banks[i] << eUnit
+ << endl << " RD Cmd Energy: " << energy.read_energy_banks[i] << eUnit
+ << endl << " WR Cmd Energy: " << energy.write_energy_banks[i] << eUnit
+ << endl << " Auto-Refresh Energy: " << energy.ref_energy_banks[i] << eUnit
+ << endl << " Bankwise-Refresh Energy: " << energy.refb_energy_banks[i] << eUnit
+ << endl << " ACT Stdby Energy: " << nRanksDouble * energy.act_stdby_energy_banks[i] << eUnit
+ << endl << " PRE Stdby Energy: " << nRanksDouble * energy.pre_stdby_energy_banks[i] << eUnit
+ << endl << " Active Idle Energy: "<< nRanksDouble * energy.idle_energy_act_banks[i] << eUnit
+ << endl << " Precharge Idle Energy: "<< nRanksDouble * energy.idle_energy_pre_banks[i] << eUnit
+ << endl << " Fast-Exit Active Power-Down Energy: "<< nRanksDouble * energy.f_act_pd_energy_banks[i] << eUnit
+ << endl << " Fast-Exit Precharged Power-Down Energy: "<< nRanksDouble * energy.f_pre_pd_energy_banks[i] << eUnit
+ << endl << " Slow-Exit Active Power-Down Energy: "<< nRanksDouble * energy.s_act_pd_energy_banks[i] << eUnit
+ << endl << " Slow-Exit Precharged Power-Down Energy: "<< nRanksDouble * energy.s_pre_pd_energy_banks[i] << eUnit
+ << endl << " Self-Refresh Energy: "<< nRanksDouble * energy.sref_energy_banks[i] << eUnit
+ << endl << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles in Self-Refresh: "<< nRanksDouble * energy.sref_ref_act_energy_banks[i] << eUnit
+ << endl << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy_banks[i] << eUnit
+ << endl << " Self-Refresh Power-Up Energy: "<< nRanksDouble * energy.spup_energy_banks[i] << eUnit
+ << endl << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: "<< nRanksDouble * energy.spup_ref_act_energy_banks[i] << eUnit
+ << endl << " Precharge Stdby Energy during Auto-Refresh cycles in Self-Refresh Power-Up: "<< nRanksDouble * energy.spup_ref_pre_energy_banks[i] << eUnit
+ << endl << " Active Power-Up Energy: "<< nRanksDouble * energy.pup_act_energy_banks[i] << eUnit
+ << endl << " Precharged Power-Up Energy: "<< nRanksDouble * energy.pup_pre_energy_banks[i] << eUnit
+ << endl << " Total Energy: "<< energy.total_energy_banks[i] << eUnit
+ << endl;
+ }
+ cout << endl;
+ }
+
cout.precision(2);
cout << endl << "* Trace Power and Energy Estimates:" << endl
<< endl << "ACT Cmd Energy: " << energy.act_energy << eUnit
@@ -308,7 +474,7 @@ void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term,
<< endl << "WR Cmd Energy: " << energy.write_energy << eUnit;
if (term) {
- cout << "RD I/O Energy: " << energy.read_io_energy << eUnit << endl;
+ cout << endl << "RD I/O Energy: " << energy.read_io_energy << eUnit << endl;
// No Termination for LPDDR/2/3 and DDR memories
if (memSpec.memArchSpec.termination) {
cout << "WR Termination Energy: " << energy.write_term_energy << eUnit << endl;
@@ -320,8 +486,6 @@ void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term,
}
}
- double nRanksDouble = static_cast<double>(nRanks);
-
cout << "ACT Stdby Energy: " << nRanksDouble * energy.act_stdby_energy << eUnit
<< endl << " Active Idle Energy: " << nRanksDouble * energy.idle_energy_act << eUnit
<< endl << " Active Power-Up Energy: " << nRanksDouble * energy.pup_act_energy << eUnit
@@ -340,6 +504,7 @@ void MemoryPowerModel::power_print(const MemorySpecification& memSpec, int term,
<< endl << " Slow-Exit Precharged Power-Down Energy: " << nRanksDouble * energy.s_pre_pd_energy << eUnit
<< endl << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh cycles in Self-Refresh: " << nRanksDouble * energy.sref_ref_pre_energy << eUnit
<< endl << "Auto-Refresh Energy: " << energy.ref_energy << eUnit
+ << endl << "Bankwise-Refresh Energy: " << sum(energy.refb_energy_banks) << eUnit
<< endl << "Self-Refresh Energy: " << nRanksDouble * energy.sref_energy << eUnit
<< endl << "----------------------------------------"
<< endl << "Total Trace Energy: " << energy.total_energy << eUnit
@@ -364,6 +529,51 @@ double MemoryPowerModel::engy_sref(double idd6, double idd3n, double idd5,
return sref_energy;
}
+// Self-refresh active energy estimation per banks
+double MemoryPowerModel::engy_sref_banks(double idd6, double idd3n, double idd5,
+ double vdd, double sref_cycles, double sref_ref_act_cycles,
+ double sref_ref_pre_cycles, double spup_ref_act_cycles,
+ double spup_ref_pre_cycles, double clk,
+ double esharedPASR, const MemBankWiseParams& bwPowerParams,
+ unsigned bnkIdx, int64_t nbrofBanks)
+{
+ // Bankwise Self-refresh energy
+ double sref_energy_banks;
+ // Dynamic componenents for PASR energy varying based on PASR mode
+ double iddsigmaDynBanks;
+ double pasr_energy_dyn;
+ // This component is distributed among all banks
+ double sref_energy_shared;
+ //Is PASR Active
+ if (bwPowerParams.flgPASR){
+ sref_energy_shared = (((idd5 - idd3n) * (sref_ref_act_cycles
+ + spup_ref_act_cycles + sref_ref_pre_cycles + spup_ref_pre_cycles)) * vdd * clk)
+ / static_cast<double>(nbrofBanks);
+ //if the bank is active under current PASR mode
+ if (bwPowerParams.isBankActiveInPasr(bnkIdx)){
+ // Distribute the sref energy to the active banks
+ iddsigmaDynBanks = (static_cast<double>(100 - bwPowerParams.bwPowerFactSigma) / (100.0 * static_cast<double>(nbrofBanks))) * idd6;
+ pasr_energy_dyn = vdd * iddsigmaDynBanks * sref_cycles;
+ // Add the static components
+ sref_energy_banks = sref_energy_shared + pasr_energy_dyn + (esharedPASR /static_cast<double>(nbrofBanks));
+
+ }else{
+ sref_energy_banks = (esharedPASR /static_cast<double>(nbrofBanks));
+ }
+ }
+ //When PASR is not active total all the banks are in Self-Refresh. Thus total Self-Refresh energy is distributed across all banks
+ else{
+
+
+ sref_energy_banks = (((idd6 * sref_cycles) + ((idd5 - idd3n) * (sref_ref_act_cycles
+ + spup_ref_act_cycles + sref_ref_pre_cycles + spup_ref_pre_cycles)))
+ * vdd * clk)
+ / static_cast<double>(nbrofBanks);
+ }
+ return sref_energy_banks;
+}
+
+
// IO and Termination power calculation based on Micron Power Calculators
// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW)
void MemoryPowerModel::io_term_power(const MemorySpecification& memSpec)
@@ -397,3 +607,4 @@ double EnergyDomain::calcTivEnergy(int64_t cycles, double current) const
{
return static_cast<double>(cycles) * clkPeriod * current * voltage;
}
+
diff --git a/ext/drampower/src/MemoryPowerModel.h b/ext/drampower/src/MemoryPowerModel.h
index 2b2304989..916d540a8 100644
--- a/ext/drampower/src/MemoryPowerModel.h
+++ b/ext/drampower/src/MemoryPowerModel.h
@@ -31,98 +31,163 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji
+ * Authors: Karthik Chandrasekar
+ * Matthias Jung
+ * Omar Naji
+ * Subash Kannoth
+ * Éder F. Zulian
+ * Felipe S. Prado
*
*/
#ifndef MEMORY_POWER_MODEL_H
#define MEMORY_POWER_MODEL_H
+#include <numeric>
#include "MemorySpecification.h"
+#include "MemBankWiseParams.h"
#include "CommandAnalysis.h"
namespace Data {
class MemoryPowerModel {
public:
+
+ MemoryPowerModel();
+
// Calculate energy and average power consumption for the given memory
// command trace
void power_calc(const MemorySpecification& memSpec,
const CommandAnalysis& c,
- int term);
+ int term,
+ const MemBankWiseParams& bwPowerParams);
// Used to calculate self-refresh active energy
static double engy_sref(double idd6,
double idd3n,
double idd5,
double vdd,
- double sref_cycles,
+ double sref_cycles_idd6,
double sref_ref_act_cycles,
double sref_ref_pre_cycles,
double spup_ref_act_cycles,
double spup_ref_pre_cycles,
double clk);
+ static double engy_sref_banks(double idd6,
+ double idd3n,
+ double idd5,
+ double vdd,
+ double sref_cycles,
+ double sref_ref_act_cycles,
+ double sref_ref_pre_cycles,
+ double spup_ref_act_cycles,
+ double spup_ref_pre_cycles,
+ double clk,
+ double esharedPASR,
+ const MemBankWiseParams& bwPowerParams,
+ unsigned bnkIdx,
+ int64_t nbrofBanks);
int64_t total_cycles;
+ int64_t window_cycles;
+
struct Energy {
// Total energy of all activates
double act_energy;
+ std::vector<double> act_energy_banks;
// Total energy of all precharges
double pre_energy;
+ std::vector<double> pre_energy_banks;
// Total energy of all reads
double read_energy;
+ std::vector<double> read_energy_banks;
// Total energy of all writes
double write_energy;
+ std::vector<double> write_energy_banks;
// Total energy of all refreshes
double ref_energy;
+ std::vector<double> ref_energy_banks;
+
+ // Bankwise refresh energy
+ std::vector<double> refb_energy_banks;
// Total background energy of all active standby cycles
double act_stdby_energy;
+ std::vector<double> act_stdby_energy_banks;
// Total background energy of all precharge standby cycles
double pre_stdby_energy;
+ std::vector<double> pre_stdby_energy_banks;
// Total energy of idle cycles in the active mode
double idle_energy_act;
+ std::vector<double> idle_energy_act_banks;
// Total energy of idle cycles in the precharge mode
double idle_energy_pre;
+ std::vector<double> idle_energy_pre_banks;
// Total trace/pattern energy
double total_energy;
+ std::vector<double> total_energy_banks;
+
+ // Window energy
+ double window_energy;
// Average Power
double average_power;
// Energy consumed in active/precharged fast/slow-exit modes
double f_act_pd_energy;
+ std::vector<double> f_act_pd_energy_banks;
+
double f_pre_pd_energy;
+ std::vector<double> f_pre_pd_energy_banks;
+
double s_act_pd_energy;
+ std::vector<double> s_act_pd_energy_banks;
+
double s_pre_pd_energy;
+ std::vector<double> s_pre_pd_energy_banks;
// Energy consumed in self-refresh mode
double sref_energy;
+ std::vector<double> sref_energy_banks;
// Energy consumed in auto-refresh during self-refresh mode
double sref_ref_energy;
+ std::vector<double> sref_ref_energy_banks;
+
double sref_ref_act_energy;
+ std::vector<double> sref_ref_act_energy_banks;
+
double sref_ref_pre_energy;
+ std::vector<double> sref_ref_pre_energy_banks;
// Energy consumed in powering-up from self-refresh mode
double spup_energy;
+ std::vector<double> spup_energy_banks;
// Energy consumed in auto-refresh during self-refresh power-up
double spup_ref_energy;
+ std::vector<double> spup_ref_energy_banks;
+
double spup_ref_act_energy;
+ std::vector<double> spup_ref_act_energy_banks;
+
double spup_ref_pre_energy;
+ std::vector<double> spup_ref_pre_energy_banks;
// Energy consumed in powering-up from active/precharged power-down modes
double pup_act_energy;
+ std::vector<double> pup_act_energy_banks;
+
double pup_pre_energy;
+ std::vector<double> pup_pre_energy_banks;
// Energy consumed by IO and Termination
double read_io_energy; // Read IO Energy
@@ -142,12 +207,16 @@ class MemoryPowerModel {
// Average Power
double average_power;
+
+ // Window Average Power
+ double window_average_power;
};
// Print the power and energy
void power_print(const MemorySpecification& memSpec,
int term,
- const CommandAnalysis& c) const;
+ const CommandAnalysis& c,
+ bool bankwiseMode) const;
// To derive IO and Termination Power measures using DRAM specification
void io_term_power(const MemorySpecification& memSpec);
@@ -157,6 +226,8 @@ class MemoryPowerModel {
private:
double calcIoTermEnergy(int64_t cycles, double period, double power, int64_t numBits) const;
+ // Sum quantities (e.g., operations, energy, cycles) that are stored in a per bank basis returning the total amount.
+ template <typename T> T sum(const std::vector<T> vec) const { return std::accumulate(vec.begin(), vec.end(), static_cast<T>(0)); }
};
class EnergyDomain {
@@ -167,6 +238,7 @@ class EnergyDomain {
{}
double calcTivEnergy(int64_t cycles, double current) const;
+ double getVoltage() const{ return voltage; };
private:
const double voltage;
const double clkPeriod;
diff --git a/ext/drampower/src/TraceParser.cc b/ext/drampower/src/TraceParser.cc
index 2cf9a8572..88f31c21f 100644
--- a/ext/drampower/src/TraceParser.cc
+++ b/ext/drampower/src/TraceParser.cc
@@ -42,8 +42,8 @@
using namespace Data;
using namespace std;
-TraceParser::TraceParser(int64_t nbrOfBanks) :
- counters(nbrOfBanks)
+TraceParser::TraceParser(const MemorySpecification& memSpec) :
+ counters(memSpec)
{
}
@@ -80,7 +80,7 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
{
ifstream pwr_trace;
- counters = CommandAnalysis(memSpec.memArchSpec.nbrOfBanks);
+ counters = CommandAnalysis(memSpec);
int nCommands = 0;
bool lastupdate = false;
if (trans) {
@@ -93,13 +93,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
cmd_list.push_back(cmdline);
nCommands++;
if (nCommands == window) {
- counters.getCommands(memSpec, cmd_list, lastupdate);
+ counters.getCommands(cmd_list, lastupdate);
nCommands = 0;
cmd_list.clear();
}
}
lastupdate = true;
- counters.getCommands(memSpec, cmd_list, lastupdate);
+ counters.getCommands(cmd_list, lastupdate);
cmd_list.clear();
pwr_trace.close();
} else {
@@ -109,13 +109,13 @@ void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace,
cmd_list.push_back(cmdline);
nCommands++;
if (nCommands == window) {
- counters.getCommands(memSpec, cmd_list, lastupdate);
+ counters.getCommands(cmd_list, lastupdate);
nCommands = 0;
cmd_list.clear();
}
}
lastupdate = true;
- counters.getCommands(memSpec, cmd_list, lastupdate);
+ counters.getCommands(cmd_list, lastupdate);
cmd_list.clear();
}
counters.clear();
diff --git a/ext/drampower/src/TraceParser.h b/ext/drampower/src/TraceParser.h
index 9727b4800..3f68ea6ef 100644
--- a/ext/drampower/src/TraceParser.h
+++ b/ext/drampower/src/TraceParser.h
@@ -48,7 +48,7 @@
class TraceParser {
public:
- TraceParser(int64_t nbrOfBanks);
+ TraceParser(const Data::MemorySpecification& memSpec);
// list of parsed commands
std::vector<Data::MemCommand> cmd_list;
diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.cc b/ext/drampower/src/libdrampower/LibDRAMPower.cc
index 47ed15a99..65eedacb5 100644
--- a/ext/drampower/src/libdrampower/LibDRAMPower.cc
+++ b/ext/drampower/src/libdrampower/LibDRAMPower.cc
@@ -31,7 +31,11 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Matthias Jung, Omar Naji
+ * Authors: Matthias Jung
+ * Omar Naji
+ * Subash Kannoth
+ * Éder F. Zulian
+ * Felipe S. Prado
*
*/
@@ -41,8 +45,19 @@ using namespace Data;
libDRAMPower::libDRAMPower(const MemorySpecification& memSpec, bool includeIoAndTermination) :
memSpec(memSpec),
- counters(CommandAnalysis(memSpec.memArchSpec.nbrOfBanks)),
- includeIoAndTermination(includeIoAndTermination)
+ counters(memSpec),
+ includeIoAndTermination(includeIoAndTermination),
+ mpm(MemoryPowerModel())
+{
+ MemBankWiseParams p (100,100,false,0,false,static_cast<unsigned>(memSpec.memArchSpec.nbrOfBanks));
+ libDRAMPower DRAMPower = libDRAMPower(memSpec, 0, p);
+}
+
+libDRAMPower::libDRAMPower(const MemorySpecification& memSpec, bool includeIoAndTermination, const Data::MemBankWiseParams& bwPowerParams) :
+ memSpec(memSpec),
+ counters(CommandAnalysis(memSpec)),
+ includeIoAndTermination(includeIoAndTermination),
+ bwPowerParams(bwPowerParams)
{
}
@@ -56,17 +71,27 @@ void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp)
cmdList.push_back(cmd);
}
-void libDRAMPower::updateCounters(bool lastUpdate)
+void libDRAMPower::updateCounters(bool lastUpdate, int64_t timestamp)
{
- counters.getCommands(memSpec, cmdList, lastUpdate);
+ counters.getCommands(cmdList, lastUpdate, timestamp);
cmdList.clear();
}
void libDRAMPower::calcEnergy()
{
- mpm.power_calc(memSpec, counters, includeIoAndTermination);
+ updateCounters(true);
+ mpm.power_calc(memSpec, counters, includeIoAndTermination, bwPowerParams);
}
+void libDRAMPower::calcWindowEnergy(int64_t timestamp)
+{
+ doCommand(MemCommand::NOP, 0, timestamp);
+ updateCounters(false, timestamp);
+ mpm.power_calc(memSpec, counters, includeIoAndTermination, bwPowerParams);
+ clearCounters(timestamp);
+}
+
+
void libDRAMPower::clearState()
{
counters.clear();
diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.h b/ext/drampower/src/libdrampower/LibDRAMPower.h
index 4d9ccefe5..46e14bdd3 100644
--- a/ext/drampower/src/libdrampower/LibDRAMPower.h
+++ b/ext/drampower/src/libdrampower/LibDRAMPower.h
@@ -31,7 +31,11 @@
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * Authors: Matthias Jung, Omar Naji
+ * Authors: Matthias Jung
+ * Omar Naji
+ * Subash Kannoth
+ * Éder F. Zulian
+ * Felipe S. Prado
*
*/
@@ -44,35 +48,42 @@
#include "CommandAnalysis.h"
#include "MemoryPowerModel.h"
#include "MemCommand.h"
+#include "MemBankWiseParams.h"
+
class libDRAMPower {
public:
libDRAMPower(const Data::MemorySpecification& memSpec, bool includeIoAndTermination);
+ libDRAMPower(const Data::MemorySpecification& memSpec, bool includeIoAndTermination,const Data::MemBankWiseParams& bwPowerParams);
~libDRAMPower();
void doCommand(Data::MemCommand::cmds type,
int bank,
int64_t timestamp);
- void updateCounters(bool lastUpdate);
-
- void clearCounters(int64_t timestamp);
-
- void clearState();
-
void calcEnergy();
+ void calcWindowEnergy(int64_t timestamp);
+
const Data::MemoryPowerModel::Energy& getEnergy() const;
const Data::MemoryPowerModel::Power& getPower() const;
// list of all commands
std::vector<Data::MemCommand> cmdList;
private:
+ void updateCounters(bool lastUpdate, int64_t timestamp = 0);
+
+ void clearCounters(int64_t timestamp);
+
+ void clearState();
+
Data::MemorySpecification memSpec;
public:
Data::CommandAnalysis counters;
private:
bool includeIoAndTermination;
+ bool bankwiseMode;
+ Data:: MemBankWiseParams bwPowerParams;
// Object of MemoryPowerModel which contains the results
// Energies(pJ) stored in energy, Powers(mW) stored in power. Number of
// each command stored in timings.