diff options
Diffstat (limited to 'ext/drampower/src')
-rw-r--r-- | ext/drampower/src/CAHelpers.cc | 118 | ||||
-rw-r--r-- | ext/drampower/src/CmdHandlers.cc | 625 | ||||
-rw-r--r-- | ext/drampower/src/CommandAnalysis.cc | 500 | ||||
-rw-r--r-- | ext/drampower/src/CommandAnalysis.h | 114 | ||||
-rw-r--r-- | ext/drampower/src/MemBankWiseParams.cc | 161 | ||||
-rw-r--r-- | ext/drampower/src/MemBankWiseParams.h | 79 | ||||
-rw-r--r-- | ext/drampower/src/MemCommand.h | 59 | ||||
-rw-r--r-- | ext/drampower/src/MemPowerSpec.cc | 2 | ||||
-rw-r--r-- | ext/drampower/src/MemPowerSpec.h | 1 | ||||
-rw-r--r-- | ext/drampower/src/MemTimingSpec.cc | 2 | ||||
-rw-r--r-- | ext/drampower/src/MemTimingSpec.h | 1 | ||||
-rw-r--r-- | ext/drampower/src/MemoryPowerModel.cc | 275 | ||||
-rw-r--r-- | ext/drampower/src/MemoryPowerModel.h | 80 | ||||
-rw-r--r-- | ext/drampower/src/TraceParser.cc | 14 | ||||
-rw-r--r-- | ext/drampower/src/TraceParser.h | 2 | ||||
-rw-r--r-- | ext/drampower/src/libdrampower/LibDRAMPower.cc | 37 | ||||
-rw-r--r-- | ext/drampower/src/libdrampower/LibDRAMPower.h | 25 |
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. |