diff options
Diffstat (limited to 'ext/drampower/src')
26 files changed, 4635 insertions, 0 deletions
diff --git a/ext/drampower/src/CmdScheduler.cc b/ext/drampower/src/CmdScheduler.cc new file mode 100644 index 000000000..bffc5d3bb --- /dev/null +++ b/ext/drampower/src/CmdScheduler.cc @@ -0,0 +1,659 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ +#include "CmdScheduler.h" + +#include <cassert> +#include <cmath> // For log2 + +#include <algorithm> // For max + + +using namespace std; +using namespace Data; + +// Read the traces and get the transaction. Each transaction is executed by +// scheduling a number of commands to the memory. Hence, the transactions are +// translated into a sequence of commands which will be used for power analysis. +void cmdScheduler::transTranslation(MemorySpecification memSpec, + ifstream& trans_trace, int grouping, int interleaving, int burst, int powerdown) +{ + commands.open("commands.trace", ifstream::out); + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + nBanks = memArchSpec.nbrOfBanks; + nColumns = memArchSpec.nbrOfColumns; + burstLength = memArchSpec.burstLength; + nbrOfBankGroups = memArchSpec.nbrOfBankGroups; + + BGI = grouping; + BI = interleaving; + BC = burst; + power_down = powerdown; + + schedulingInitialization(memSpec); + getTrans(trans_trace, memSpec); + + trans_trace.close(); + commands.close(); + ACT.erase(ACT.begin(), ACT.end()); + PRE.erase(PRE.begin(), PRE.end()); + RDWR.erase(RDWR.begin(), RDWR.end()); + cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end()); + cmdList.erase(cmdList.begin(), cmdList.end()); + transTrace.erase(transTrace.begin(), transTrace.end()); +} // cmdScheduler::transTranslation + +// initialize the variables and vectors for starting command scheduling. +void cmdScheduler::schedulingInitialization(MemorySpecification memSpec) +{ + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + + ACT.resize(2 * memSpec.memArchSpec.nbrOfBanks); + RDWR.resize(2 * memSpec.memArchSpec.nbrOfBanks); + PRE.resize(memSpec.memArchSpec.nbrOfBanks); + bankaccess = memSpec.memArchSpec.nbrOfBanks; + if (!ACT.empty()) { + ACT.erase(ACT.begin(), ACT.end()); + } + if (!PRE.empty()) { + PRE.erase(PRE.begin(), PRE.end()); + } + if (!RDWR.empty()) { + RDWR.erase(RDWR.begin(), RDWR.end()); + } + + ///////////////initialization////////////// + for (unsigned i = 0; i < memSpec.memArchSpec.nbrOfBanks; i++) { + cmd.Type = PRECHARGE; + cmd.bank = i; + cmd.name = "PRE"; + if (memSpec.id == "WIDEIO_SDR") + cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.TAW); + else + cmd.time = 1 - static_cast<double>(memSpec.memTimingSpec.FAW); + + PRE.push_back(cmd); + + cmd.Type = ACTIVATE; + cmd.name = "ACT"; + ACT.push_back(cmd); + + cmd.Type = WRITE; + cmd.name = "WRITE"; + cmd.time = -1; + RDWR[i].push_back(cmd); + } + tREF = memTimingSpec.REFI; + transFinish.time = 0; + transFinish.bank = 0; + + PreRDWR.bank = -1; + PreRDWR.Type = READ; + PreRDWR.name = "RD"; + PreRDWR.time = -1; + startTime = 0; +} // cmdScheduler::schedulingInitialization + +// transactions are generated according to the information read from the traces. +// Then the command scheduling function is triggered to generate commands and +// schedule them to the memory according to the timing constraints. +void cmdScheduler::getTrans(std::ifstream& trans_trace, MemorySpecification memSpec) +{ + std::string line; + + transTime = 0; + unsigned newtranstime; + unsigned transAddr; + unsigned transType = 1; + trans TransItem; + + if (!transTrace.empty()) { + transTrace.erase(transTrace.begin(), transTrace.end()); + } + + while (getline(trans_trace, line)) { + istringstream linestream(line); + string item; + unsigned itemnum = 0; + while (getline(linestream, item, ',')) { + if (itemnum == 0) { + stringstream timestamp(item); + timestamp >> newtranstime; + transTime = transTime + newtranstime; + } else if (itemnum == 1) { + if (item == "write" || item == "WRITE") { + transType = WRITE; + } else { + transType = READ; + } + } else if (itemnum == 2) { + stringstream timestamp(item); + timestamp >> std::hex >> transAddr; + } + itemnum++; + } + // generate a transaction + TransItem.timeStamp = transTime; + TransItem.logicalAddress = transAddr; + TransItem.type = transType; + + transTrace.push_back(TransItem); + + if (transTrace.size() == MILLION) { + // The scheduling is implemented for every MILLION transactions. + // It is used to reduce the used memory during the running of this tool. + analyticalScheduling(memSpec); + transTrace.erase(transTrace.begin(), transTrace.end()); + } + } + + if ((transTrace.size() < MILLION) && (!transTrace.empty())) { + analyticalScheduling(memSpec); + transTrace.erase(transTrace.begin(), transTrace.end()); + } +} // cmdScheduler::getTrans + +// Transactions are executed individually and the command scheduling is +// independent between transactions. The commands for a new transaction cannot +// be scheduled until all the commands for the current one are scheduled. +// After the scheduling, a sequence of commands are obtained and they are written +// into commands.txt which will be used for power analysis. +void cmdScheduler::analyticalScheduling(MemorySpecification memSpec) +{ + int Bs = -1; + int transType = -1; + double timer = 0; + int bankGroupPointer = 0; + int bankGroupAddr = 0; + bool collisionFound; + physicalAddr PhysicalAddress; + bool bankGroupSwitch = false; + std::vector<unsigned> bankPointer(nbrOfBankGroups, 0); + std::vector<int> bankAccessNum(nBanks, -1); + std::vector<bool> ACTSchedule(nBanks, false); + int bankAddr = -1; + double endTime = 0; + double tComing_REF = 0; + + Inselfrefresh = 0; + + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + + for (unsigned t = 0; t < transTrace.size(); t++) { + cmdScheduling.erase(cmdScheduling.begin(), cmdScheduling.end()); + + for (unsigned i = 0; i < nBanks; i++) { + ACTSchedule[i] = false; + bankAccessNum[i] = -1; + } + + timingsGet = false; + timer = transTrace[t].timeStamp; + + PhysicalAddress = memoryMap(transTrace[t], memSpec); + + for (unsigned i = 0; i < nbrOfBankGroups; i++) { + bankPointer[i] = PhysicalAddress.bankAddr; // the bank pointer per group. + } + bankGroupPointer = PhysicalAddress.bankGroupAddr; + + endTime = max(transFinish.time, PRE[transFinish.bank].time + + static_cast<int>(memTimingSpec.RP)); + + // Before starting the scheduling for the next transaction, it has to + // check whether it is necessary for implementing power down. + if (power_down == SELF_REFRESH) + pdScheduling(endTime, timer, memSpec); + else if (power_down == POWER_DOWN) + pdScheduling(endTime, min(timer, tREF), memSpec); + + tComing_REF = tREF; + + ///////////////Scheduling Refresh//////////////////////// + if (((transFinish.time >= tREF) || (timer >= tREF))) { + for (double i = 0; i <= ((timer - tComing_REF) > 0 ? (timer - tComing_REF) / + memTimingSpec.REFI : 0); i++) { + cmd.bank = 0; + cmd.name = "REF"; + cmd.time = max(max(max(transFinish.time, PRE[transFinish.bank].time + + static_cast<int>(memTimingSpec.RP)), tREF), startTime); + if (((power_down == SELF_REFRESH) && !Inselfrefresh) || + (power_down != SELF_REFRESH)) { + cmdScheduling.push_back(cmd); + startTime = cmd.time + memTimingSpec.RFC; + } + tREF = tREF + memTimingSpec.REFI; + // during the refreshing, power down should be taken into account. + if (!Inselfrefresh) + pdScheduling(endTime, min(timer, tREF), memSpec); + } + } + ///////////////Execution Transactions/////////////////// + Bs = PhysicalAddress.bankAddr; + transType = transTrace[t].type; + + tRWTP = getRWTP(transType, memSpec); + + for (int i = 0; i < BI; i++) { + for (int k = 0; k < BC; k++) { + if (memSpec.memoryType == MemoryType::DDR4) { + bankGroupPointer = PhysicalAddress.bankGroupAddr; + } + + for (int j = 0; j < BGI; j++) { + bankGroupSwitch = false; + if (memSpec.memoryType == MemoryType::DDR4) { + if (bankGroupPointer != bankGroupAddr) { + bankGroupSwitch = true; + } + // update to the current bank group address. + bankGroupAddr = PhysicalAddress.bankGroupAddr + j; + bankAddr = bankGroupAddr * nBanks / nbrOfBankGroups + + bankPointer[bankGroupAddr]; + } else { + bankAddr = Bs + i; + } + + if (!timingsGet) { + getTimingConstraints(bankGroupSwitch, memSpec, + PreRDWR.Type, transType); + } + + ////////////////ACT Scheduling/////////////////// + if (!ACTSchedule[bankAddr]) { + cmd.bank = bankAddr; + cmd.PhysicalAddr.bankAddr = cmd.bank; + cmd.PhysicalAddr.rowAddr = PhysicalAddress.rowAddr; + cmd.Type = ACTIVATE; + cmd.name = "ACT"; + Inselfrefresh = 0; + cmd.time = max(max(ACT[bankaccess - 1].time + tRRD_init, + PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)), + ACT[bankaccess - 4].time + + static_cast<int>(memTimingSpec.FAW)); + + if (memSpec.memoryType == MemoryType::WIDEIO_SDR) { + cmd.time = max(max(ACT[bankaccess - 1].time + tRRD_init, + PRE[cmd.bank].time + static_cast<int>(memTimingSpec.RP)), + ACT[bankaccess - 2].time + + static_cast<int>(memTimingSpec.TAW)); + } + + if ((i == 0) && (j == 0)) { + cmd.time = max(cmd.time, PreRDWR.time + 1); + cmd.time = max(cmd.time, timer); + cmd.time = max(startTime, cmd.time); + } + + //////////collision detection//////////////////// + for (int n = 1; n <= i * BGI + j; n++) { + collisionFound = false; + for (unsigned m = 0; m < RDWR[bankaccess - n].size(); m++) { + if (RDWR[bankaccess - n][m].time == cmd.time) { + cmd.time += 1; // ACT is shifted + collisionFound = true; + break; + } + } + if (collisionFound) { + break; + } + } + + ACT.push_back(cmd); + cmdScheduling.push_back(cmd); + + ACTSchedule[bankAddr] = true; + bankAccessNum[bankAddr] = bankaccess; + bankaccess++; + } + + /////RDWR Scheduling////// + cmd.bank = bankAddr; + cmd.PhysicalAddr.bankAddr = cmd.bank; + cmd.PhysicalAddr.rowAddr = PhysicalAddress.rowAddr; + cmd.PhysicalAddr.colAddr = PhysicalAddress.colAddr + k * burstLength; + cmd.Type = transType; + switch (transType) { + case READ: + cmd.name = "RD"; + break; + + case WRITE: + cmd.name = "WR"; + break; + } + for (int ACTBank = static_cast<int>(ACT.size() - 1); + ACTBank >= 0; ACTBank--) { + if (ACT[ACTBank].bank == bankAddr) { + cmd.time = max(PreRDWR.time + tSwitch_init, ACT.back().time + + static_cast<int>(memTimingSpec.RCD)); + break; + } + } + + if ((i == BI - 1) && (k == BC - 1) && (j == BGI - 1)) { + transFinish.time = cmd.time + 1; + transFinish.bank = bankAddr; + } + if (k == BC - 1) { + switch (transType) { + case READ: + cmd.name = "RDA"; + break; + + case WRITE: + cmd.name = "WRA"; + break; + } + } + PreRDWR = cmd; + + RDWR[bankAccessNum[bankAddr]].push_back(cmd); + cmdScheduling.push_back(cmd); + + ////////////////PRE Scheduling//////////////////// + if (k == BC - 1) { + PRE[bankAddr].bank = bankAddr; + PRE[bankAddr].Type = PRECHARGE; + PRE[bankAddr].name = "PRE"; + for (int ACTBank = static_cast<int>(ACT.size() - 1); + ACTBank >= 0; ACTBank--) { + if (ACT[ACTBank].bank == bankAddr) { + PRE[bankAddr].time = max(ACT.back().time + + static_cast<int>(memTimingSpec.RAS), + PreRDWR.time + tRWTP); + break; + } + } + bankPointer[bankGroupAddr] = bankPointer[bankGroupAddr] + 1; + } + + bankGroupPointer++; + } + } + } + + // make sure the scheduled commands are stored with an ascending scheduling time + sort(cmdScheduling.begin(), cmdScheduling.end(), + commandItem::commandItemSorter()); + + // write the scheduled commands into commands.txt. + for (unsigned i = 0; i < cmdScheduling.size(); i++) { + cmdList.push_back(cmdScheduling[i]); + } + + /////////////Update Vector Length///////////////// + // the vector length is reduced so that less memory is used for running + // this tool. + if (ACT.size() >= memSpec.memArchSpec.nbrOfBanks) { + for (int m = 0; m < BI * BGI; m++) { + ACT.erase(ACT.begin()); + RDWR[0].erase(RDWR[0].begin(), RDWR[0].end()); + for (int h = 0; h < bankaccess - 1 - m; h++) { + RDWR[h].insert(RDWR[h].begin(), RDWR[h + 1].begin(), RDWR[h + 1].end()); + RDWR[h + 1].resize(0); + } + } + bankaccess = bankaccess - (BI * BGI); + } + } + + for (unsigned j = 0; j < cmdList.size(); j++) { + commands.precision(0); + commands << fixed << cmdList[j].time << "," << cmdList[j].name << "," << + cmdList[j].bank << endl; + } + cmdList.erase(cmdList.begin(), cmdList.end()); +} // cmdScheduler::analyticalScheduling + +// to add the power down/up during the command scheduling for transactions. +// It is called when the command scheduling for a transaction is finished, and it +// is also called if there is a refresh. +void cmdScheduler::pdScheduling(double endTime, double timer, + MemorySpecification memSpec) +{ + double ZERO = 0; + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + + endTime = max(endTime, startTime); + double pdTime = max(ZERO, timer - endTime); + + if ((timer > (endTime + memTimingSpec.CKE)) && (power_down == POWER_DOWN)) { + cmd.bank = 0; + cmd.name = "PDN_S_PRE"; + cmd.time = endTime; + cmdScheduling.push_back(cmd); + cmd.name = "PUP_PRE"; + + if (pdTime > memTimingSpec.REFI) + cmd.time = cmd.time + memTimingSpec.REFI; + else + cmd.time = cmd.time + pdTime; + + if (memSpec.memoryType.isLPDDRFamily()) + startTime = cmd.time + memTimingSpec.XP; + else + startTime = cmd.time + memTimingSpec.XPDLL - memTimingSpec.RCD; + + cmdScheduling.push_back(cmd); + } else if ((timer > (endTime + memTimingSpec.CKESR)) && (power_down == SELF_REFRESH)) { + cmd.bank = 0; + cmd.name = "SREN"; + cmd.time = endTime; + cmdScheduling.push_back(cmd); + Inselfrefresh = 1; + cmd.name = "SREX"; + cmd.time = cmd.time + pdTime; + + if (memSpec.memoryType.isLPDDRFamily()) + startTime = cmd.time + memTimingSpec.XS; + else + startTime = cmd.time + memTimingSpec.XSDLL - memTimingSpec.RCD; + + cmdScheduling.push_back(cmd); + } +} // cmdScheduler::pdScheduling + +// get the time when a precharge occurs after a read/write command is scheduled. +// In addition, it copes with different kind of memories. +int cmdScheduler::getRWTP(int transType, MemorySpecification memSpec) +{ + int tRWTP_init = 0; + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + + if (transType == READ) { + switch (memSpec.memoryType) { + case MemoryType::LPDDR: + case MemoryType::WIDEIO_SDR: + tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate; + break; + + case MemoryType::LPDDR2: + case MemoryType::LPDDR3: + tRWTP_init = memArchSpec.burstLength / memArchSpec.dataRate + + max(0, static_cast<int>(memTimingSpec.RTP - 2)); + break; + + case MemoryType::DDR2: + tRWTP_init = memTimingSpec.AL + memArchSpec.burstLength / + memArchSpec.dataRate + + max(static_cast<int>(memTimingSpec.RTP), 2) - 2; + break; + + case MemoryType::DDR3: + case MemoryType::DDR4: + tRWTP_init = memTimingSpec.RTP; + break; + default: + assert("Unknown memory type" && false); + } // switch + } else if (transType == WRITE) { + if (memSpec.memoryType == MemoryType::WIDEIO_SDR) { + tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength / + memArchSpec.dataRate - 1 + memSpec.memTimingSpec.WR; + } else { + tRWTP_init = memTimingSpec.WL + memArchSpec.burstLength / + memArchSpec.dataRate + memSpec.memTimingSpec.WR; + } + if ((memSpec.memoryType == MemoryType::LPDDR2) || + (memSpec.memoryType == MemoryType::LPDDR3)) { + tRWTP_init = tRWTP_init + 1; + } + } + + return tRWTP_init; +} // cmdScheduler::getRWTP + +// get the timings for command scheduling according to different memories. +// In particular, tSwitch_init is generally used to provide the timings for +// scheduling a read/write command after a read/write command which have been +// scheduled to any possible banks within any possible bank groups (DDR4). +void cmdScheduler::getTimingConstraints(bool BGSwitch, MemorySpecification memSpec, + int PreType, int CurrentType) +{ + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + + if (memSpec.memoryType != MemoryType::DDR4) { + tRRD_init = memTimingSpec.RRD; + if (PreType == CurrentType) { + tSwitch_init = memTimingSpec.CCD; + timingsGet = true; + } + + if ((PreType == WRITE) && (CurrentType == READ)) { + if (memSpec.memoryType == MemoryType::WIDEIO_SDR) { + tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength / + memArchSpec.dataRate - 1 + memTimingSpec.WTR; + } else { + tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength / + memArchSpec.dataRate + memTimingSpec.WTR; + } + + if ((memSpec.memoryType == MemoryType::LPDDR2) || + (memSpec.memoryType == MemoryType::LPDDR3)) { + tSwitch_init = tSwitch_init + 1; + } + } + } + + if (memSpec.memoryType == MemoryType::DDR4) { + if (BGSwitch) { + tCCD_init = memTimingSpec.CCD_S; + tRRD_init = memTimingSpec.RRD_S; + tWTR_init = memTimingSpec.WTR_S; + } else { + tCCD_init = memTimingSpec.CCD_L; + tRRD_init = memTimingSpec.RRD_L; + tWTR_init = memTimingSpec.WTR_L; + } + + if (PreType == CurrentType) { + tSwitch_init = tCCD_init; + timingsGet = true; + } else if ((PreType == WRITE) && (CurrentType == READ)) { + tSwitch_init = memTimingSpec.WL + memArchSpec.burstLength / + memArchSpec.dataRate + tWTR_init; + } + } + + if ((PreType == READ) && (CurrentType == WRITE)) { + tSwitch_init = memTimingSpec.RL + memArchSpec.burstLength / + memArchSpec.dataRate + 2 - memTimingSpec.WL; + } +} // cmdScheduler::getTimingConstraints + +// The logical address of each transaction is translated into a physical address +// which consists of bank group (for DDR4), bank, row and column addresses. +cmdScheduler::physicalAddr cmdScheduler::memoryMap(trans Trans, + MemorySpecification memSpec) +{ + int DecLogic; + physicalAddr PhysicalAddr; + + DecLogic = Trans.logicalAddress; + + // row-bank-column-BI-BC-BGI-BL + if ((BGI > 1) && (memSpec.memoryType == MemoryType::DDR4)) { + unsigned colBits = static_cast<unsigned>(log2(nColumns)); + unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0) + + ((BGI > 1) ? log2(BGI) : 0)); + unsigned bankMask = static_cast<unsigned>(nBanks / (BI * nbrOfBankGroups) - 1) + << bankShift; + unsigned bankAddr = (DecLogic & bankMask) >> + static_cast<unsigned>(colBits + ((BGI > 1) ? log2(BGI) : 0)); + PhysicalAddr.bankAddr = bankAddr; + + unsigned bankGroupShift = static_cast<unsigned>(log2(burstLength)); + unsigned bankGroupMask = (nbrOfBankGroups / BGI - 1) << bankGroupShift; + unsigned bankGroupAddr = (DecLogic & bankGroupMask) >> bankGroupShift; + PhysicalAddr.bankGroupAddr = bankGroupAddr; + + unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) + + ((BI > 1) ? log2(BI) : 0) + ((BGI > 1) ? log2(BGI) : 0)); + unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1) + << colShift; + unsigned colAddr = (DecLogic & colMask) >> + static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength))); + PhysicalAddr.colAddr = colAddr; + } else { + unsigned colBits = static_cast<unsigned>(log2(nColumns)); + unsigned bankShift = static_cast<unsigned>(colBits + ((BI > 1) ? log2(BI) : 0)); + unsigned bankMask = static_cast<unsigned>(nBanks / BI - 1) << bankShift; + unsigned bankAddr = (DecLogic & bankMask) >> colBits; + PhysicalAddr.bankAddr = bankAddr; + + unsigned colShift = static_cast<unsigned>(log2(BC * burstLength) + + ((BI > 1) ? log2(BI) : 0)); + unsigned colMask = static_cast<unsigned>(nColumns / (BC * burstLength) - 1) + << colShift; + unsigned colAddr = (DecLogic & colMask) >> + static_cast<unsigned>((colShift - log2(static_cast<unsigned>(BC) * burstLength))); + PhysicalAddr.colAddr = colAddr; + + PhysicalAddr.bankGroupAddr = 0; + } + + unsigned rowShift = static_cast<unsigned>(log2(nColumns * nBanks)); + unsigned rowMask = static_cast<unsigned>(memSpec.memArchSpec.nbrOfRows - 1) + << rowShift; + unsigned rowAddr = (DecLogic & rowMask) >> rowShift; + PhysicalAddr.rowAddr = rowAddr; + + return PhysicalAddr; +} // cmdScheduler::memoryMap diff --git a/ext/drampower/src/CmdScheduler.h b/ext/drampower/src/CmdScheduler.h new file mode 100644 index 000000000..3c60ea886 --- /dev/null +++ b/ext/drampower/src/CmdScheduler.h @@ -0,0 +1,168 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#ifndef CMDSCHEDULER_H +#define CMDSCHEDULER_H + +#include <string> +#include <vector> +#include <functional> // for binary_function<> +#include <fstream> + +#include "MemorySpecification.h" +#include "Utils.h" + +namespace Data { +class cmdScheduler { + public: + #define READ 0 + #define WRITE 1 + #define ACTIVATE 2 + #define PRECHARGE 3 + #define POWER_DOWN 1 + #define SELF_REFRESH 2 + + // the format of a transaction. + class trans { + public: + int type; + double timeStamp; + unsigned logicalAddress; + }; + + std::vector<trans> transTrace; // to store the transactions. + + // the format of physical address. + class physicalAddr { + public: + unsigned rowAddr; + unsigned bankAddr; + unsigned bankGroupAddr; + unsigned colAddr; + }; + + // the format of a command. + class commandItem { + public: + int Type; + int bank; + double time; + std::string name; + physicalAddr PhysicalAddr; + // sorting the commands according to their scheduling time. + struct commandItemSorter : public std::binary_function<commandItem&, + commandItem&, bool>{ + bool operator()(const commandItem& lhs, + const commandItem& rhs) const + { + return lhs.time < rhs.time; + } + }; + }; + + commandItem cmd; + commandItem transFinish; // the last scheduled command for a transaction. + commandItem PreRDWR; // the latest scheduled READ or WRITE command. + // the scheduled ACTIVATE commands are stored in ACT. + std::vector<commandItem> ACT; + // PRE is sued to keep recording the time when a precharge occurs. + std::vector<commandItem> PRE; + // the scheduled READ or WRITE commands are stored in RDWR. + std::vector<std::vector<commandItem> > RDWR; + // all the scheduled commands for a transaction is stored by cmdScheduling. + std::vector<commandItem> cmdScheduling; + std::vector<commandItem> cmdList; + unsigned elements; + int BI, BC, BGI; + + // the function used to translate a transaction into a sequence of + // commands which are scheduled to the memory. + void transTranslation(Data::MemorySpecification memSpec, + std::ifstream& trans_trace, + int grouping, + int interleaving, + int burst, + int powerdown); + // get the transactions by reading the traces. + void getTrans(std::ifstream& pwr_trace, + MemorySpecification memSpec); + // the initialization function for scheduling. + void schedulingInitialization(MemorySpecification memSpec); + // the function used to schedule commands according to the timing constraints. + void analyticalScheduling(MemorySpecification memSpec); + // translate the logical address into physical address. + physicalAddr memoryMap(trans Trans, + MemorySpecification memSpec); + // the power down and power up are scheduled by pdScheduling + void pdScheduling(double endTime, + double timer, + MemorySpecification memSpec); + // get the timings for scheduling a precharge since a read or write command + // is scheduled. + int getRWTP(int transType, + MemorySpecification memSpec); + // get different kind of timing constraints according to the used memory. + void getTimingConstraints(bool BGSwitch, + MemorySpecification memSpec, + int PreType, + int CurrentType); + + double transTime; + // the flag for power down. + int power_down; + int Inselfrefresh; + int tRRD_init; + int tCCD_init; + int tWTR_init; + double tREF; + double tSwitch_init; + double tRWTP; + int bankaccess; + unsigned nBanks; + unsigned nColumns; + unsigned burstLength; + unsigned nbrOfBankGroups; + bool timingsGet; + double startTime; + + // the scheduling results for all the transactions are written into + // commands which will be used by the power analysis part. + std::ofstream commands; +}; +} + +#endif // ifndef CMDSCHEDULER_H diff --git a/ext/drampower/src/CommandAnalysis.cc b/ext/drampower/src/CommandAnalysis.cc new file mode 100644 index 000000000..4dea5c101 --- /dev/null +++ b/ext/drampower/src/CommandAnalysis.cc @@ -0,0 +1,666 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji, Sven Goossens + * + */ + +#include <fstream> +#include <algorithm> +#include <sstream> + +#include "CommandAnalysis.h" +#include "CmdScheduler.h" + +using namespace Data; +using namespace std; + +CommandAnalysis::CommandAnalysis() +{ +} + +CommandAnalysis::CommandAnalysis(const int nbrofBanks) +{ + // Initializing all counters and variables + + numberofacts = 0; + numberofpres = 0; + numberofreads = 0; + numberofwrites = 0; + numberofrefs = 0; + f_act_pdns = 0; + s_act_pdns = 0; + f_pre_pdns = 0; + s_pre_pdns = 0; + numberofsrefs = 0; + + pop = 0; + init = 0; + zero = 0; + + actcycles = 0; + precycles = 0; + f_act_pdcycles = 0; + s_act_pdcycles = 0; + f_pre_pdcycles = 0; + s_pre_pdcycles = 0; + pup_act_cycles = 0; + pup_pre_cycles = 0; + sref_cycles = 0; + spup_cycles = 0; + sref_ref_act_cycles = 0; + sref_ref_pre_cycles = 0; + spup_ref_act_cycles = 0; + spup_ref_pre_cycles = 0; + idlecycles_act = 0; + idlecycles_pre = 0; + + latest_act_cycle = -1; + latest_pre_cycle = -1; + latest_read_cycle = -1; + latest_write_cycle = -1; + end_read_op = 0; + end_write_op = 0; + end_act_op = 0; + + first_act_cycle = 0; + last_pre_cycle = 0; + + bankstate.resize(nbrofBanks, 0); + last_states.resize(nbrofBanks); + mem_state = 0; + + sref_cycle = 0; + pdn_cycle = 0; + + cmd_list.clear(); + full_cmd_list.resize(1, MemCommand::PRE); + cached_cmd.clear(); + activation_cycle.resize(nbrofBanks, 0); +} + +// function to clear all arrays +void CommandAnalysis::clear() +{ + cached_cmd.clear(); + cmd_list.clear(); + full_cmd_list.clear(); + last_states.clear(); + bankstate.clear(); +} + +// Reads through the trace file, identifies the timestamp, command and bank +// If the issued command includes an auto-precharge, adds an explicit +// 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, + const int nbrofBanks, std::vector<MemCommand>& list, bool lastupdate) +{ + for (vector<MemCommand>::const_iterator i = list.begin(); i != list.end(); ++i) { + const MemCommand& cmd = *i; + cmd_list.push_back(cmd); + + MemCommand::cmds cmdType = cmd.getType(); + if (cmdType == MemCommand::ACT) { + activation_cycle[cmd.getBank()] = cmd.getTimeInt64(); + } else if (cmdType == MemCommand::RDA || cmdType == MemCommand::WRA) { + // Remove auto-precharge flag from command + cmd_list.back().setType(cmd.typeWithoutAutoPrechargeFlag()); + + // Add the auto precharge to the list of cached_cmds + int64_t preTime = max(cmd.getTimeInt64() + cmd.getPrechargeOffset(memSpec, cmdType), + activation_cycle[cmd.getBank()] + memSpec.memTimingSpec.RAS); + cached_cmd.push_back(MemCommand(MemCommand::PRE, cmd.getBank(), static_cast<double>(preTime))); + } + } + pop = 0; + // Note: the extra pre-cmds at the end of the lists, and the cast to double + // of the size vector is probably not desirable. + cmd_list.push_back(MemCommand::PRE); + cached_cmd.push_back(MemCommand::PRE); + analyse_commands(nbrofBanks, memSpec, cmd_list.size()-1, + cached_cmd.size()-1, lastupdate); + cmd_list.clear(); + cached_cmd.clear(); +} // CommandAnalysis::getCommands + +// Checks the auto-precharge cached command list and inserts the explicit +// precharges with the appropriate timestamp in the original command list +// (by merging) based on their offset from the issuing command. Calls the +// evaluate function to analyse this expanded list of commands. + +void CommandAnalysis::analyse_commands(const int nbrofBanks, + Data::MemorySpecification memSpec, int64_t nCommands, int64_t nCached, bool lastupdate) +{ + full_cmd_list.resize(1, MemCommand::PRE); + unsigned mCommands = 0; + unsigned mCached = 0; + for (unsigned i = 0; i < nCommands + nCached + 1; i++) { + if (cached_cmd.size() > 1) { + if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) { + full_cmd_list[i].setType(MemCommand::PREA); + init = 1; + pop = 1; + } else { + init = 1; + if ((cached_cmd[mCached].getTime() > 0) && (cmd_list. + at(mCommands).getTime() < cached_cmd[mCached]. + getTime()) && ((cmd_list[mCommands].getTime() > 0) || + ((cmd_list[mCommands].getTime() == 0) && (cmd_list[mCommands]. + getType() != MemCommand::PRE)))) { + full_cmd_list[i] = cmd_list[mCommands]; + mCommands++; + } else if ((cached_cmd[mCached].getTime() > 0) && (cmd_list[mCommands]. + getTime() >= cached_cmd[mCached].getTime())) { + full_cmd_list[i] = cached_cmd[mCached]; + mCached++; + } else if (cached_cmd[mCached].getTime() == 0) { + if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list[mCommands]. + getTime() == 0) && (cmd_list[mCommands]. + getType() != MemCommand::PRE))) { + full_cmd_list[i] = cmd_list[mCommands]; + mCommands++; + } + } else if (cmd_list[mCommands].getTime() == 0) { + full_cmd_list[i] = cached_cmd[mCached]; + mCached++; + } + } + } else { + if ((cmd_list[mCommands].getTime() > 1) && (init == 0)) { + full_cmd_list[i].setType(MemCommand::PREA); + init = 1; + pop = 1; + } else { + init = 1; + if ((cmd_list[mCommands].getTime() > 0) || ((cmd_list. + at(mCommands).getTime() == 0) && (cmd_list[mCommands]. + getType() != MemCommand::PRE))) { + full_cmd_list[i] = cmd_list[mCommands]; + mCommands++; + } + } + } + full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::PRE); + } + + full_cmd_list.pop_back(); + if (pop == 0) { + full_cmd_list.pop_back(); + } + if (lastupdate) { + full_cmd_list.resize(full_cmd_list.size() + 1, MemCommand::NOP); + full_cmd_list[full_cmd_list.size() - 1].setTime(full_cmd_list + [full_cmd_list.size() - 2].getTime() + timeToCompletion(memSpec, + full_cmd_list[full_cmd_list.size() - 2].getType()) - 1); + } + + evaluate(memSpec, full_cmd_list, nbrofBanks); +} // CommandAnalysis::analyse_commands + +// To get the time of completion of the issued command +// Derived based on JEDEC specifications + +int CommandAnalysis::timeToCompletion(const MemorySpecification& + memSpec, MemCommand::cmds type) +{ + int offset = 0; + const MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + const MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + + if (type == MemCommand::RD) { + offset = static_cast<int>(memTimingSpec.RL + + memTimingSpec.DQSCK + 1 + (memArchSpec.burstLength / + memArchSpec.dataRate)); + } else if (type == MemCommand::WR) { + offset = static_cast<int>(memTimingSpec.WL + + (memArchSpec.burstLength / memArchSpec.dataRate) + + memTimingSpec.WR); + } else if (type == MemCommand::ACT) { + offset = static_cast<int>(memTimingSpec.RCD); + } else if ((type == MemCommand::PRE) || (type == MemCommand::PREA)) { + offset = static_cast<int>(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, int nbrofBanks) +{ + // for each command identify timestamp, type and bank + for (unsigned cmd_list_counter = 0; cmd_list_counter < cmd_list.size(); + cmd_list_counter++) { + // For command type + int type = cmd_list[cmd_list_counter].getType(); + // For command bank + int bank = cmd_list[cmd_list_counter].getBank(); + // Command Issue timestamp in clock cycles (cc) + int64_t timestamp = cmd_list[cmd_list_counter].getTimeInt64(); + + if (type == MemCommand::ACT) { + // If command is ACT - update number of acts, bank state of the + // target bank, first and latest activation cycle and the memory + // state. Update the number of precharged/idle-precharged cycles. + numberofacts++; + if (bankstate[bank] == 1) { + printWarning("Bank is already active!", type, timestamp, bank); + } + bankstate[bank] = 1; + if (mem_state == 0) { + first_act_cycle = timestamp; + precycles += max(zero, timestamp - last_pre_cycle); + idle_pre_update(memSpec, timestamp, latest_pre_cycle); + } + latest_act_cycle = timestamp; + mem_state++; + } else if (type == MemCommand::RD) { + // If command is RD - update number of reads and read cycle. Check + // for active idle cycles (if any). + if (bankstate[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; + } else if (type == MemCommand::WR) { + // If command is WR - update number of writes and write cycle. Check + // for active idle cycles (if any). + if (bankstate[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; + } else if (type == MemCommand::REF) { + // 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; + mem_state = 0; + for (int j = 0; j < nbrofBanks; j++) { + bankstate[j] = 0; + } + } else if (type == MemCommand::PRE) { + // If command is explicit PRE - update number of precharges, bank + // state of the target bank and last and latest precharge cycle. + // Calculate the number of active cycles if the memory was in the + // active state before, but there is a state transition to PRE now. + // If not, update the number of precharged cycles and idle cycles. + // Update memory state if needed. + if (bankstate[bank] == 1) { + numberofpres++; + } + bankstate[bank] = 0; + + if (mem_state == 1) { + actcycles += max(zero, timestamp - first_act_cycle); + last_pre_cycle = timestamp; + idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, + latest_act_cycle, timestamp); + } else if (mem_state == 0) { + precycles += max(zero, timestamp - last_pre_cycle); + idle_pre_update(memSpec, timestamp, latest_pre_cycle); + last_pre_cycle = timestamp; + } + latest_pre_cycle = timestamp; + if (mem_state > 0) { + mem_state--; + } else { + mem_state = 0; + } + } else if (type == MemCommand::PREA) { + // If command is explicit PREA (precharge all banks) - update + // number of precharges by the number of banks, update the bank + // state of all banks to PRE and set the precharge cycle. + // Calculate the number of active cycles if the memory was in the + // active state before, but there is a state transition to PRE now. + // If not, update the number of precharged cycles and idle cycles. + if (timestamp == 0) { + numberofpres += 0; + } else { + numberofpres += mem_state; + } + + if (mem_state > 0) { + actcycles += max(zero, timestamp - first_act_cycle); + idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, + latest_act_cycle, timestamp); + } else if (mem_state == 0) { + precycles += max(zero, timestamp - last_pre_cycle); + idle_pre_update(memSpec, timestamp, latest_pre_cycle); + } + + latest_pre_cycle = timestamp; + last_pre_cycle = timestamp; + + mem_state = 0; + + for (int j = 0; j < nbrofBanks; j++) { + bankstate[j] = 0; + } + } 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++; + for (int j = 0; j < nbrofBanks; j++) { + last_states[j] = bankstate[j]; + } + 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; + } 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++; + for (int j = 0; j < nbrofBanks; j++) { + last_states[j] = bankstate[j]; + } + 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; + } 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; + } 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; + } 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; + } + mem_state = 0; + for (int j = 0; j < nbrofBanks; j++) { + bankstate[j] = last_states[j]; + mem_state += last_states[j]; + } + first_act_cycle = 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; + last_pre_cycle = 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; + } 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; + } else if ((type == MemCommand::END) || (type == MemCommand::NOP)) { + // May be optionally used at the end of memory trace for better accuracy + // Update all counters based on completion of operations. + if ((mem_state > 0) && (mem_state < 9)) { + actcycles += max(zero, timestamp - first_act_cycle); + idle_act_update(memSpec, latest_read_cycle, latest_write_cycle, + latest_act_cycle, timestamp); + } else if (mem_state == 0) { + 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); + } + } + } +} // CommandAnalysis::evaluate + +// 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, + int64_t latest_act_cycle, int64_t timestamp) +{ + if (latest_read_cycle >= 0) { + end_read_op = latest_read_cycle + timeToCompletion(memSpec, + MemCommand::RD) - 1; + } + + if (latest_write_cycle >= 0) { + end_write_op = latest_write_cycle + timeToCompletion(memSpec, + MemCommand::WR) - 1; + } + + if (latest_act_cycle >= 0) { + end_act_op = latest_act_cycle + timeToCompletion(memSpec, + MemCommand::ACT) - 1; + } + + idlecycles_act += max(zero, timestamp - max(max(end_read_op, end_write_op), + end_act_op)); +} // 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) +{ + if (latest_pre_cycle > 0) { + idlecycles_pre += max(zero, timestamp - latest_pre_cycle - + memSpec.memTimingSpec.RP); + } else if (latest_pre_cycle == 0) { + idlecycles_pre += max(zero, timestamp - latest_pre_cycle); + } +} + +void CommandAnalysis::printWarningIfActive(const string& warning, int type, int64_t timestamp, int bank) +{ + if (mem_state != 0) { + printWarning(warning, type, timestamp, bank); + } +} + +void CommandAnalysis::printWarningIfNotActive(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 new file mode 100644 index 000000000..b5c7ac778 --- /dev/null +++ b/ext/drampower/src/CommandAnalysis.h @@ -0,0 +1,213 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji + * + */ + +#ifndef COMMAND_TIMINGS_H +#define COMMAND_TIMINGS_H + +#include <stdint.h> + +#include <vector> +#include <iostream> +#include <deque> +#include <string> + +#include "MemCommand.h" +#include "MemorySpecification.h" +#include "Utils.h" + +namespace Data { +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_PDN_S_PRE = 13, MS_SREF = 14 + }; + + CommandAnalysis(); + + // Returns number of reads, writes, acts, pres and refs in the trace + CommandAnalysis(const int 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; + // Number of refresh commands + int64_t numberofrefs; + // Number of precharge cycles + int64_t precycles; + // Number of active cycles + int64_t actcycles; + // Number of Idle cycles in the active state + int64_t idlecycles_act; + // Number of Idle cycles in the precharge state + int64_t idlecycles_pre; + // Number of fast-exit activate power-downs + int64_t f_act_pdns; + // Number of slow-exit activate power-downs + int64_t s_act_pdns; + // Number of fast-exit precharged power-downs + int64_t f_pre_pdns; + // Number of slow-exit activate power-downs + int64_t s_pre_pdns; + // Number of self-refresh commands + int64_t numberofsrefs; + // Number of clock cycles in fast-exit activate power-down mode + int64_t f_act_pdcycles; + // Number of clock cycles in slow-exit activate power-down mode + int64_t s_act_pdcycles; + // Number of clock cycles in fast-exit precharged power-down mode + 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 + int64_t sref_cycles; + // Number of clock cycles in activate power-up mode + int64_t pup_act_cycles; + // Number of clock cycles in precharged power-up mode + int64_t pup_pre_cycles; + // Number of clock cycles in self-refresh power-up mode + int64_t spup_cycles; + + // Number of active auto-refresh cycles in self-refresh mode + int64_t sref_ref_act_cycles; + // Number of precharged auto-refresh cycles in self-refresh mode + int64_t sref_ref_pre_cycles; + // 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 + int64_t spup_ref_pre_cycles; + + // function for clearing arrays + void clear(); + + // To identify auto-precharges + void getCommands(const MemorySpecification& memSpec, + const int + nbrofBanks, + std::vector<MemCommand>& list, + bool lastupdate); + + private: + unsigned init; + int64_t zero; + unsigned pop; + // Cached last read command from the file + std::vector<MemCommand> cached_cmd; + + // Stores the memory commands for analysis + std::vector<MemCommand> cmd_list; + + // Stores all memory commands for analysis + std::vector<MemCommand> full_cmd_list; + + // To save states of the different banks, before entering active + // power-down mode (slow/fast-exit). + std::vector<int> last_states; + // Bank state vector + std::vector<int> bankstate; + + std::vector<int64_t> activation_cycle; + // To keep track of the last ACT cycle + int64_t latest_act_cycle; + // To keep track of the last PRE cycle + int64_t latest_pre_cycle; + // To keep track of the last READ cycle + int64_t latest_read_cycle; + // To keep track of the last WRITE cycle + int64_t latest_write_cycle; + + // To calculate end of READ operation + int64_t end_read_op; + // To calculate end of WRITE operation + int64_t end_write_op; + // To calculate end of ACT operation + int64_t end_act_op; + + // Clock cycle when self-refresh was issued + int64_t sref_cycle; + + // Clock cycle when the latest power-down was issued + int64_t pdn_cycle; + + // Memory State + unsigned mem_state; + + // Clock cycle of first activate command when memory state changes to ACT + int64_t first_act_cycle; + + // Clock cycle of last precharge command when memory state changes to PRE + int64_t last_pre_cycle; + // To collect and analyse all commands including auto-precharges + void analyse_commands(const int nbrofBanks, + Data::MemorySpecification + memSpec, + int64_t nCommands, + int64_t nCached, + bool lastupdate); + // To perform timing analysis of a given set of commands and update command counters + void evaluate(const MemorySpecification& memSpec, + std::vector<MemCommand>& cmd_list, + int nbrofBanks); + + // To calculate time of completion of any issued command + int timeToCompletion(const MemorySpecification& memSpec, + 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, + 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, + 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 printWarning(const std::string& warning, int type, int64_t timestamp, int bank); +}; +} +#endif // ifndef COMMAND_TIMINGS_H diff --git a/ext/drampower/src/MemArchitectureSpec.cc b/ext/drampower/src/MemArchitectureSpec.cc new file mode 100644 index 000000000..f3155853d --- /dev/null +++ b/ext/drampower/src/MemArchitectureSpec.cc @@ -0,0 +1,74 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "MemArchitectureSpec.h" + +#include <cassert> + +using namespace Data; + +MemArchitectureSpec::MemArchitectureSpec() : + burstLength(0), + nbrOfBanks(0), + nbrOfRanks(0), + dataRate(0), + nbrOfColumns(0), + nbrOfRows(0), + width(0), + nbrOfBankGroups(0), + dll(false), + twoVoltageDomains(false), + termination(false) +{ +} + +void MemArchitectureSpec::processParameters() +{ + // Load all parameters in our member variables + nbrOfBanks = getParamValWithDefault("nbrOfBanks", 1); + nbrOfRanks = getParamValWithDefault("nbrOfRanks", 1); + nbrOfBankGroups = getParamValWithDefault("nbrOfBankGroups", 1); + dataRate = getParamValWithDefault("dataRate", 1); + burstLength = getParamValWithDefault("burstLength", 1); + nbrOfColumns = getParamValWithDefault("nbrOfColumns", 1); + nbrOfRows = getParamValWithDefault("nbrOfRows", 1); + width = getParamValWithDefault("width", 1); + assert("memory width should be a multiple of 8" && (width % 8) == 0); + dll = getParamValWithDefault("dll", false); + twoVoltageDomains = getParamValWithDefault("twoVoltageDomains", false); + termination = getParamValWithDefault("termination", false); +} diff --git a/ext/drampower/src/MemArchitectureSpec.h b/ext/drampower/src/MemArchitectureSpec.h new file mode 100644 index 000000000..ca79edc91 --- /dev/null +++ b/ext/drampower/src/MemArchitectureSpec.h @@ -0,0 +1,62 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H +#define TOOLS_MEM_ARCHITECTURE_SPEC_H + +#include "Parametrisable.h" + +namespace Data { +class MemArchitectureSpec : public virtual Parametrisable { + public: + MemArchitectureSpec(); + void processParameters(); + + unsigned int burstLength; + unsigned nbrOfBanks; + unsigned nbrOfRanks; + unsigned dataRate; + unsigned nbrOfColumns; + unsigned nbrOfRows; + unsigned width; + unsigned nbrOfBankGroups; + bool dll; + bool twoVoltageDomains; + bool termination; +}; +} +#endif // ifndef TOOLS_MEM_ARCHITECTURE_SPEC_H diff --git a/ext/drampower/src/MemCommand.cc b/ext/drampower/src/MemCommand.cc new file mode 100644 index 000000000..156716c2f --- /dev/null +++ b/ext/drampower/src/MemCommand.cc @@ -0,0 +1,159 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "MemCommand.h" + +#include <algorithm> // for max + +#include "MemorySpecification.h" + +using namespace Data; +using namespace std; + +MemCommand::MemCommand() : + type(MemCommand::PRE), + bank(0), + timestamp(0) +{ +} + +MemCommand::MemCommand(MemCommand::cmds type, + unsigned bank, double timestamp) : + type(type), + bank(bank), + timestamp(timestamp) +{ +} + +void MemCommand::setType(MemCommand::cmds _type) +{ + type = _type; +} + +MemCommand::cmds MemCommand::getType() const +{ + return type; +} + +void MemCommand::setBank(unsigned _bank) +{ + bank = _bank; +} + +unsigned MemCommand::getBank() const +{ + return bank; +} + +// For auto-precharge with read or write - to calculate cycle of precharge +int MemCommand::getPrechargeOffset(const MemorySpecification& memSpec, + MemCommand::cmds type) const +{ + int precharge_offset = 0; + + int BL(static_cast<int>(memSpec.memArchSpec.burstLength)); + int RTP(static_cast<int>(memSpec.memTimingSpec.RTP)); + int dataRate(static_cast<int>(memSpec.memArchSpec.dataRate)); + int AL(static_cast<int>(memSpec.memTimingSpec.AL)); + int WL(static_cast<int>(memSpec.memTimingSpec.WL)); + int WR(static_cast<int>(memSpec.memTimingSpec.WR)); + int B = BL/dataRate; + + const MemoryType::MemoryType_t& memType = memSpec.memoryType; + + // Read with auto-precharge + if (type == MemCommand::RDA) { + if (memType == MemoryType::DDR2) { + precharge_offset = B + AL - 2 + max(RTP, 2); + } else if (memType == MemoryType::DDR3) { + precharge_offset = AL + max(RTP, 4); + } else if (memType == MemoryType::DDR4) { + precharge_offset = AL + RTP; + } else if (memType == MemoryType::LPDDR) { + precharge_offset = B; + } else if (memType == MemoryType::LPDDR2) { + precharge_offset = B + max(0, RTP - 2); + } else if (memType == MemoryType::LPDDR3) { + precharge_offset = B + max(0, RTP - 4); + } else if (memType == MemoryType::WIDEIO_SDR) { + precharge_offset = B; + } + } else if (type == MemCommand::WRA) { // Write with auto-precharge + if (memType == MemoryType::DDR2) { + precharge_offset = B + WL + WR; + } else if (memType == MemoryType::DDR3) { + precharge_offset = B + WL + WR; + } else if (memType == MemoryType::DDR4) { + precharge_offset = B + WL + WR; + } else if (memType == MemoryType::LPDDR) { + precharge_offset = B + WR; // + DQSS actually, but we don't have that parameter. + } else if (memType == MemoryType::LPDDR2) { + precharge_offset = B + WL + WR + 1; + } else if (memType == MemoryType::LPDDR3) { + precharge_offset = B + WL + WR + 1; + } else if (memType == MemoryType::WIDEIO_SDR) { + precharge_offset = B + WL + WR - 1; + } + } + + return precharge_offset; +} // MemCommand::getPrechargeOffset + +void MemCommand::setTime(double _timestamp) +{ + timestamp = _timestamp; +} + +double MemCommand::getTime() const +{ + return timestamp; +} + +int64_t MemCommand::getTimeInt64() const +{ + return static_cast<int64_t>(timestamp); +} + +MemCommand::cmds MemCommand::typeWithoutAutoPrechargeFlag() const +{ + if (type == MemCommand::RDA) { + return MemCommand::RD; + } else if (type == MemCommand::WRA) { + return MemCommand::WR; + } + return type; +} diff --git a/ext/drampower/src/MemCommand.h b/ext/drampower/src/MemCommand.h new file mode 100644 index 000000000..4159fe008 --- /dev/null +++ b/ext/drampower/src/MemCommand.h @@ -0,0 +1,170 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#ifndef MEMCOMMAND_H +#define MEMCOMMAND_H + +#include <stdint.h> +#include <cassert> +#include <string> + +#include "MemorySpecification.h" + +namespace Data { +class MemCommand { + public: + /* + * 1. ACT - Activate + * 2. RD - Read + * 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 + */ + + enum cmds { + ACT = 0, + RD = 1, + 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 + }; + + MemCommand(); + MemCommand( + // Command Type + MemCommand::cmds type, + // Target Bank + unsigned bank = 0, + // Command Issue Timestamp (in cc) + double timestamp = 0); + + // Get command type + cmds getType() const; + + // Set command type + void setType(MemCommand::cmds type); + + // Set target Bank + void setBank(unsigned bank); + + // Get target Bank + unsigned getBank() const; + + // Set timestamp + void setTime(double _timestamp); + + // Get timestamp + double getTime() const; + int64_t getTimeInt64() const; + + cmds typeWithoutAutoPrechargeFlag() const; + + // To calculate precharge offset after read or write with auto-precharge + int getPrechargeOffset(const MemorySpecification& memSpec, + MemCommand::cmds type) const; + + // To check for equivalence + + bool operator==(const MemCommand& other) const + { + if ((getType() == other.getType()) && + (getBank() == other.getBank()) + ) { + return true; + } else { + return false; + } + } + + static const unsigned int nCommands = 18; + + static std::string* getCommandTypeStrings() + { + static std::string type_map[nCommands] = { "ACT", "RD", "WR", "PRE", "REF", + "END", "RDA", "WRA", "PREA", "PDN_F_PRE","PDN_S_PRE", "PDN_F_ACT", + "PDN_S_ACT", "PUP_PRE", "PUP_ACT", "SREN", "SREX", "NOP" }; + + return type_map; + } + + // To identify command type from name + static cmds getTypeFromName(const std::string name) + { + std::string* typeStrings = getCommandTypeStrings(); + + for (size_t typeId = 0; typeId < nCommands; typeId++) { + if (typeStrings[typeId] == name) { + cmds commandType = static_cast<cmds>(typeId); + return commandType; + } + } + assert(false); // Unknown name. + } + + private: + MemCommand::cmds type; + unsigned bank; + double timestamp; +}; +} +#endif // ifndef MEMCOMMAND_H diff --git a/ext/drampower/src/MemPowerSpec.cc b/ext/drampower/src/MemPowerSpec.cc new file mode 100644 index 000000000..3fbc53992 --- /dev/null +++ b/ext/drampower/src/MemPowerSpec.cc @@ -0,0 +1,107 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "MemPowerSpec.h" + +using namespace Data; + +MemPowerSpec::MemPowerSpec() : + idd0(0.0), + idd02(0.0), + idd2p0(0.0), + idd2p02(0.0), + idd2p1(0.0), + idd2p12(0.0), + idd2n(0.0), + idd2n2(0.0), + idd3p0(0.0), + idd3p02(0.0), + idd3p1(0.0), + idd3p12(0.0), + idd3n(0.0), + idd3n2(0.0), + idd4r(0.0), + idd4r2(0.0), + idd4w(0.0), + idd4w2(0.0), + idd5(0.0), + idd52(0.0), + idd6(0.0), + idd62(0.0), + vdd(0.0), + vdd2(0.0), + capacitance(0.0), + ioPower(0.0), + wrOdtPower(0.0), + termRdPower(0.0), + termWrPower(0.0) +{ +} + +void MemPowerSpec::processParameters() +{ + idd0 = getParamValWithDefault("idd0", 0.0); + idd02 = getParamValWithDefault("idd02", 0.0); + idd2p0 = getParamValWithDefault("idd2p0", 0.0); + idd2p02 = getParamValWithDefault("idd2p02", 0.0); + idd2p1 = getParamValWithDefault("idd2p1", 0.0); + idd2p12 = getParamValWithDefault("idd2p12", 0.0); + idd2n = getParamValWithDefault("idd2n", 0.0); + idd2n2 = getParamValWithDefault("idd2n2", 0.0); + idd3p0 = getParamValWithDefault("idd3p0", 0.0); + idd3p02 = getParamValWithDefault("idd3p02", 0.0); + idd3p1 = getParamValWithDefault("idd3p1", 0.0); + idd3p12 = getParamValWithDefault("idd3p12", 0.0); + idd3n = getParamValWithDefault("idd3n", 0.0); + idd3n2 = getParamValWithDefault("idd3n2", 0.0); + idd4r = getParamValWithDefault("idd4r", 0.0); + idd4r2 = getParamValWithDefault("idd4r2", 0.0); + idd4w = getParamValWithDefault("idd4w", 0.0); + idd4w2 = getParamValWithDefault("idd4w2", 0.0); + idd5 = getParamValWithDefault("idd5", 0.0); + idd52 = getParamValWithDefault("idd52", 0.0); + idd6 = getParamValWithDefault("idd6", 0.0); + idd62 = getParamValWithDefault("idd62", 0.0); + vdd = getParamValWithDefault("vdd", 0.0); + vdd2 = getParamValWithDefault("vdd2", 0.0); + + capacitance = getParamValWithDefault("capacitance", 0.0); + ioPower = getParamValWithDefault("ioPower", 0.0); + wrOdtPower = getParamValWithDefault("wrOdtPower", 0.0); + termRdPower = getParamValWithDefault("termRdPower", 0.0); + termWrPower = getParamValWithDefault("termWrPower", 0.0); +} // MemPowerSpec::processParameters diff --git a/ext/drampower/src/MemPowerSpec.h b/ext/drampower/src/MemPowerSpec.h new file mode 100644 index 000000000..f6958820d --- /dev/null +++ b/ext/drampower/src/MemPowerSpec.h @@ -0,0 +1,77 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "Parametrisable.h" + +namespace Data { +class MemPowerSpec : public virtual Parametrisable { + public: + MemPowerSpec(); + void processParameters(); + + double idd0; + double idd02; + double idd2p0; + double idd2p02; + double idd2p1; + double idd2p12; + double idd2n; + double idd2n2; + double idd3p0; + double idd3p02; + double idd3p1; + double idd3p12; + double idd3n; + double idd3n2; + double idd4r; + double idd4r2; + double idd4w; + double idd4w2; + double idd5; + double idd52; + double idd6; + double idd62; + double vdd; + double vdd2; + + double capacitance; + double ioPower; + double wrOdtPower; + double termRdPower; + double termWrPower; +}; +} diff --git a/ext/drampower/src/MemTimingSpec.cc b/ext/drampower/src/MemTimingSpec.cc new file mode 100644 index 000000000..cf18c5f7b --- /dev/null +++ b/ext/drampower/src/MemTimingSpec.cc @@ -0,0 +1,110 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "MemTimingSpec.h" + +using namespace Data; + +MemTimingSpec::MemTimingSpec() : + clkMhz(0.0), + RC(0), + RCD(0), + CCD(0), + CCD_S(0), + CCD_L(0), + RRD(0), + RRD_S(0), + RRD_L(0), + FAW(0), + TAW(0), + WTR(0), + WTR_S(0), + WTR_L(0), + REFI(0), + RL(0), + RP(0), + RFC(0), + RAS(0), + WL(0), + AL(0), + DQSCK(0), + RTP(0), + WR(0), + XP(0), + XPDLL(0), + XS(0), + XSDLL(0), + CKE(0), + CKESR(0), + clkPeriod(0.0) +{ +} + +void MemTimingSpec::processParameters() +{ + clkMhz = getParamValWithDefault("clkMhz", 0.0); + RC = getParamValWithDefault("RC", 0); + RCD = getParamValWithDefault("RCD", 0); + CCD = getParamValWithDefault("CCD", 0); + RRD = getParamValWithDefault("RRD", 0); + WTR = getParamValWithDefault("WTR", 0); + CCD_S = getParamValWithDefault("CCD_S", 0); + CCD_L = getParamValWithDefault("CCD_L", 0); + RRD_S = getParamValWithDefault("RRD_S", 0); + RRD_L = getParamValWithDefault("RRD_L", 0); + WTR_S = getParamValWithDefault("WTR_S", 0); + WTR_L = getParamValWithDefault("WTR_L", 0); + TAW = getParamValWithDefault("TAW", 0); + FAW = getParamValWithDefault("FAW", 0); + REFI = getParamValWithDefault("REFI", 0); + RL = getParamValWithDefault("RL", 0); + RP = getParamValWithDefault("RP", 0); + RFC = getParamValWithDefault("RFC", 0); + RAS = getParamValWithDefault("RAS", 0); + WL = getParamValWithDefault("WL", 0); + AL = getParamValWithDefault("AL", 0); + DQSCK = getParamValWithDefault("DQSCK", 0); + RTP = getParamValWithDefault("RTP", 0); + WR = getParamValWithDefault("WR", 0); + XP = getParamValWithDefault("XP", 0); + XPDLL = getParamValWithDefault("XPDLL", 0); + XS = getParamValWithDefault("XS", 0); + XSDLL = getParamValWithDefault("XSDLL", 0); + CKE = getParamValWithDefault("CKE", 0); + CKESR = getParamValWithDefault("CKESR", 0); + clkPeriod = 1000.0 / clkMhz; +} // MemTimingSpec::processParameters diff --git a/ext/drampower/src/MemTimingSpec.h b/ext/drampower/src/MemTimingSpec.h new file mode 100644 index 000000000..1c3a80c6e --- /dev/null +++ b/ext/drampower/src/MemTimingSpec.h @@ -0,0 +1,78 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "Parametrisable.h" + +namespace Data { +class MemTimingSpec : public virtual Parametrisable { + public: + MemTimingSpec(); + void processParameters(); + + double clkMhz; + unsigned RC; + unsigned RCD; + unsigned CCD; + unsigned CCD_S; + unsigned CCD_L; + unsigned RRD; + unsigned RRD_S; + unsigned RRD_L; + unsigned FAW; + unsigned TAW; + unsigned WTR; + unsigned WTR_S; + unsigned WTR_L; + unsigned REFI; + unsigned RL; + unsigned RP; + unsigned RFC; + unsigned RAS; + unsigned WL; + unsigned AL; + unsigned DQSCK; + unsigned RTP; + unsigned WR; + unsigned XP; + unsigned XPDLL; + unsigned XS; + unsigned XSDLL; + unsigned CKE; + unsigned CKESR; + double clkPeriod; +}; +} diff --git a/ext/drampower/src/MemoryPowerModel.cc b/ext/drampower/src/MemoryPowerModel.cc new file mode 100644 index 000000000..4817d1bb5 --- /dev/null +++ b/ext/drampower/src/MemoryPowerModel.cc @@ -0,0 +1,428 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji + * + */ + +#include "MemoryPowerModel.h" + +#include <cmath> // For pow + +#include <stdint.h> + + +using namespace std; +using namespace Data; + +// Calculate energy and average power consumption for the given command trace + +void MemoryPowerModel::power_calc(MemorySpecification memSpec, + const CommandAnalysis& counters, + int term) +{ + MemTimingSpec& t = memSpec.memTimingSpec; + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + MemPowerSpec& mps = memSpec.memPowerSpec; + + energy.act_energy = 0.0; + energy.pre_energy = 0.0; + energy.read_energy = 0.0; + energy.write_energy = 0.0; + energy.ref_energy = 0.0; + energy.act_stdby_energy = 0.0; + energy.pre_stdby_energy = 0.0; + energy.idle_energy_act = 0.0; + energy.idle_energy_pre = 0.0; + energy.total_energy = 0.0; + energy.f_act_pd_energy = 0.0; + energy.f_pre_pd_energy = 0.0; + energy.s_act_pd_energy = 0.0; + energy.s_pre_pd_energy = 0.0; + energy.sref_energy = 0.0; + energy.sref_ref_energy = 0.0; + energy.sref_ref_act_energy = 0.0; + energy.sref_ref_pre_energy = 0.0; + energy.spup_energy = 0.0; + energy.spup_ref_energy = 0.0; + energy.spup_ref_act_energy = 0.0; + energy.spup_ref_pre_energy = 0.0; + energy.pup_act_energy = 0.0; + energy.pup_pre_energy = 0.0; + power.IO_power = 0.0; + power.WR_ODT_power = 0.0; + power.TermRD_power = 0.0; + power.TermWR_power = 0.0; + energy.read_io_energy = 0.0; + energy.write_term_energy = 0.0; + energy.read_oterm_energy = 0.0; + energy.write_oterm_energy = 0.0; + energy.io_term_energy = 0.0; + + // How long a single burst takes, measured in command-clock cycles. + int64_t burstCc = memArchSpec.burstLength / memArchSpec.dataRate; + + // IO and Termination Power measures are included, if required. + if (term) { + io_term_power(memSpec); + + // memArchSpec.width represents the number of data (dq) pins. + // 1 DQS pin is associated with every data byte + int64_t dqPlusDqsBits = memArchSpec.width + memArchSpec.width / 8; + // 1 DQS and 1 DM pin is associated with every data byte + int64_t dqPlusDqsPlusMaskBits = memArchSpec.width + memArchSpec.width / 8 + memArchSpec.width / 8; + // Size of one clock period for the data bus. + double ddrPeriod = t.clkPeriod / memArchSpec.dataRate; + + // Read IO power is consumed by each DQ (data) and DQS (data strobe) pin + energy.read_io_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength, + ddrPeriod, + power.IO_power, + dqPlusDqsBits); + + // Write ODT power is consumed by each DQ (data), DQS (data strobe) and DM + energy.write_term_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength, + ddrPeriod, + power.WR_ODT_power, + dqPlusDqsPlusMaskBits); + + if (memArchSpec.nbrOfRanks > 1) { + // Termination power consumed in the idle rank during reads on the active + // rank by each DQ (data) and DQS (data strobe) pin. + energy.read_oterm_energy = calcIoTermEnergy(counters.numberofreads * memArchSpec.burstLength, + ddrPeriod, + power.TermRD_power, + dqPlusDqsBits); + + // Termination power consumed in the idle rank during writes on the active + // rank by each DQ (data), DQS (data strobe) and DM (data mask) pin. + energy.write_oterm_energy = calcIoTermEnergy(counters.numberofwrites * memArchSpec.burstLength, + ddrPeriod, + power.TermWR_power, + dqPlusDqsPlusMaskBits); + } + + // Sum of all IO and termination energy + energy.io_term_energy = energy.read_io_energy + energy.write_term_energy + + energy.read_oterm_energy + energy.write_oterm_energy; + } + + total_cycles = counters.actcycles + counters.precycles + + counters.f_act_pdcycles + counters.f_pre_pdcycles + + counters.s_act_pdcycles + counters.s_pre_pdcycles + counters.sref_cycles + + counters.sref_ref_act_cycles + counters.sref_ref_pre_cycles + + counters.spup_ref_act_cycles + counters.spup_ref_pre_cycles; + + EnergyDomain vdd0Domain(mps.vdd, t.clkPeriod); + + energy.act_energy = vdd0Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd0 - mps.idd3n); + energy.pre_energy = vdd0Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd0 - mps.idd2n); + energy.read_energy = vdd0Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r - mps.idd3n); + energy.write_energy = vdd0Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w - mps.idd3n); + energy.ref_energy = vdd0Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd5 - mps.idd3n); + energy.pre_stdby_energy = vdd0Domain.calcTivEnergy(counters.precycles, mps.idd2n); + energy.act_stdby_energy = vdd0Domain.calcTivEnergy(counters.actcycles, mps.idd3n); + // Idle energy in the active standby clock cycles + energy.idle_energy_act = vdd0Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n); + // Idle energy in the precharge standby clock cycles + energy.idle_energy_pre = vdd0Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n); + // fast-exit active power-down cycles energy + energy.f_act_pd_energy = vdd0Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p1); + // fast-exit precharged power-down cycles energy + energy.f_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p1); + // slow-exit active power-down cycles energy + energy.s_act_pd_energy = vdd0Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p0); + // slow-exit precharged power-down cycles energy + energy.s_pre_pd_energy = vdd0Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p0); + + // self-refresh cycles energy including a refresh per self-refresh entry + energy.sref_energy = engy_sref(mps.idd6, mps.idd3n, + mps.idd5, mps.vdd, + static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles), + static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles), + static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod); + + // background energy during active auto-refresh cycles in self-refresh + energy.sref_ref_act_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p0); + // background energy during precharged auto-refresh cycles in self-refresh + energy.sref_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p0); + // background energy during active auto-refresh cycles in self-refresh exit + energy.spup_ref_act_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n); + // background energy during precharged auto-refresh cycles in self-refresh exit + energy.spup_ref_pre_energy = vdd0Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n); + // self-refresh power-up cycles energy -- included + energy.spup_energy = vdd0Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n); + // active power-up cycles energy - same as active standby -- included + energy.pup_act_energy = vdd0Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n); + // precharged power-up cycles energy - same as precharged standby -- included + energy.pup_pre_energy = vdd0Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n); + + // similar equations as before to support multiple voltage domains in LPDDR2 + // and WIDEIO memories + if (memArchSpec.twoVoltageDomains) { + EnergyDomain vdd2Domain(mps.vdd2, t.clkPeriod); + + energy.act_energy += vdd2Domain.calcTivEnergy(counters.numberofacts * t.RAS , mps.idd02 - mps.idd3n2); + energy.pre_energy += vdd2Domain.calcTivEnergy(counters.numberofpres * (t.RC - t.RAS) , mps.idd02 - mps.idd2n2); + energy.read_energy += vdd2Domain.calcTivEnergy(counters.numberofreads * burstCc , mps.idd4r2 - mps.idd3n2); + energy.write_energy += vdd2Domain.calcTivEnergy(counters.numberofwrites * burstCc , mps.idd4w2 - mps.idd3n2); + energy.ref_energy += vdd2Domain.calcTivEnergy(counters.numberofrefs * t.RFC , mps.idd52 - mps.idd3n2); + energy.pre_stdby_energy += vdd2Domain.calcTivEnergy(counters.precycles, mps.idd2n2); + energy.act_stdby_energy += vdd2Domain.calcTivEnergy(counters.actcycles, mps.idd3n2); + // Idle energy in the active standby clock cycles + energy.idle_energy_act += vdd2Domain.calcTivEnergy(counters.idlecycles_act, mps.idd3n2); + // Idle energy in the precharge standby clock cycles + energy.idle_energy_pre += vdd2Domain.calcTivEnergy(counters.idlecycles_pre, mps.idd2n2); + // fast-exit active power-down cycles energy + energy.f_act_pd_energy += vdd2Domain.calcTivEnergy(counters.f_act_pdcycles, mps.idd3p12); + // fast-exit precharged power-down cycles energy + energy.f_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.f_pre_pdcycles, mps.idd2p12); + // slow-exit active power-down cycles energy + energy.s_act_pd_energy += vdd2Domain.calcTivEnergy(counters.s_act_pdcycles, mps.idd3p02); + // slow-exit precharged power-down cycles energy + energy.s_pre_pd_energy += vdd2Domain.calcTivEnergy(counters.s_pre_pdcycles, mps.idd2p02); + + energy.sref_energy += engy_sref(mps.idd62, mps.idd3n2, + mps.idd52, mps.vdd2, + static_cast<double>(counters.sref_cycles), static_cast<double>(counters.sref_ref_act_cycles), + static_cast<double>(counters.sref_ref_pre_cycles), static_cast<double>(counters.spup_ref_act_cycles), + static_cast<double>(counters.spup_ref_pre_cycles), t.clkPeriod); + + // background energy during active auto-refresh cycles in self-refresh + energy.sref_ref_act_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_act_cycles, mps.idd3p02); + // background energy during precharged auto-refresh cycles in self-refresh + energy.sref_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.sref_ref_pre_cycles, mps.idd2p02); + // background energy during active auto-refresh cycles in self-refresh exit + energy.spup_ref_act_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_act_cycles, mps.idd3n2); + // background energy during precharged auto-refresh cycles in self-refresh exit + energy.spup_ref_pre_energy += vdd2Domain.calcTivEnergy(counters.spup_ref_pre_cycles, mps.idd2n2); + // self-refresh power-up cycles energy -- included + energy.spup_energy += vdd2Domain.calcTivEnergy(counters.spup_cycles, mps.idd2n2); + // active power-up cycles energy - same as active standby -- included + energy.pup_act_energy += vdd2Domain.calcTivEnergy(counters.pup_act_cycles, mps.idd3n2); + // precharged power-up cycles energy - same as precharged standby -- included + energy.pup_pre_energy += vdd2Domain.calcTivEnergy(counters.pup_pre_cycles, mps.idd2n2); + } + + // auto-refresh energy during self-refresh cycles + energy.sref_ref_energy = energy.sref_ref_act_energy + energy.sref_ref_pre_energy; + + // auto-refresh energy during self-refresh exit cycles + energy.spup_ref_energy = energy.spup_ref_act_energy + energy.spup_ref_pre_energy; + + // 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 + + 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); + + // 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(MemorySpecification memSpec, int term, const CommandAnalysis& counters) const +{ + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + + cout.precision(0); + cout << "* Trace Details:" << endl; + cout << "Number of Activates: " << fixed << counters.numberofacts << endl; + cout << "Number of Reads: " << counters.numberofreads << endl; + cout << "Number of Writes: " << counters.numberofwrites << endl; + cout << "Number of Precharges: " << counters.numberofpres << endl; + cout << "Number of Refreshes: " << counters.numberofrefs << endl; + cout << "Number of Active Cycles: " << counters.actcycles << endl; + cout << " Number of Active Idle Cycles: " << counters.idlecycles_act << endl; + cout << " Number of Active Power-Up Cycles: " << counters.pup_act_cycles << endl; + cout << " Number of Auto-Refresh Active cycles during Self-Refresh " << + "Power-Up: " << counters.spup_ref_act_cycles << endl; + cout << "Number of Precharged Cycles: " << counters.precycles << endl; + cout << " Number of Precharged Idle Cycles: " << counters.idlecycles_pre << endl; + cout << " Number of Precharged Power-Up Cycles: " << counters.pup_pre_cycles + << endl; + cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh" + << " Power-Up: " << counters.spup_ref_pre_cycles << endl; + cout << " Number of Self-Refresh Power-Up Cycles: " << counters.spup_cycles + << endl; + cout << "Total Idle Cycles (Active + Precharged): " << + counters.idlecycles_act + counters.idlecycles_pre << endl; + cout << "Number of Power-Downs: " << counters.f_act_pdns + + counters.s_act_pdns + counters.f_pre_pdns + counters.s_pre_pdns << endl; + cout << " Number of Active Fast-exit Power-Downs: " << counters.f_act_pdns + << endl; + cout << " Number of Active Slow-exit Power-Downs: " << counters.s_act_pdns + << endl; + cout << " Number of Precharged Fast-exit Power-Downs: " << + counters.f_pre_pdns << endl; + cout << " Number of Precharged Slow-exit Power-Downs: " << + counters.s_pre_pdns << endl; + cout << "Number of Power-Down Cycles: " << counters.f_act_pdcycles + + counters.s_act_pdcycles + counters.f_pre_pdcycles + counters.s_pre_pdcycles << endl; + cout << " Number of Active Fast-exit Power-Down Cycles: " << + counters.f_act_pdcycles << endl; + cout << " Number of Active Slow-exit Power-Down Cycles: " << + counters.s_act_pdcycles << endl; + cout << " Number of Auto-Refresh Active cycles during Self-Refresh: " << + counters.sref_ref_act_cycles << endl; + cout << " Number of Precharged Fast-exit Power-Down Cycles: " << + counters.f_pre_pdcycles << endl; + cout << " Number of Precharged Slow-exit Power-Down Cycles: " << + counters.s_pre_pdcycles << endl; + cout << " Number of Auto-Refresh Precharged cycles during Self-Refresh: " << + counters.sref_ref_pre_cycles << endl; + cout << "Number of Auto-Refresh Cycles: " << counters.numberofrefs * + memTimingSpec.RFC << endl; + cout << "Number of Self-Refreshes: " << counters.numberofsrefs << endl; + cout << "Number of Self-Refresh Cycles: " << counters.sref_cycles << endl; + cout << "----------------------------------------" << endl; + cout << "Total Trace Length (clock cycles): " << total_cycles << endl; + cout << "----------------------------------------" << endl; + cout.precision(2); + + cout << "\n* Trace Power and Energy Estimates:" << endl; + cout << "ACT Cmd Energy: " << energy.act_energy << " pJ" << endl; + cout << "PRE Cmd Energy: " << energy.pre_energy << " pJ" << endl; + cout << "RD Cmd Energy: " << energy.read_energy << " pJ" << endl; + cout << "WR Cmd Energy: " << energy.write_energy << " pJ" << endl; + if (term) { + cout << "RD I/O Energy: " << energy.read_io_energy << " pJ" << endl; + // No Termination for LPDDR/2/3 and DDR memories + if (memSpec.memArchSpec.termination) { + cout << "WR Termination Energy: " << energy.write_term_energy << " pJ" << endl; + } + + if ((memArchSpec.nbrOfRanks > 1) && memSpec.memArchSpec.termination) { + cout << "RD Termination Energy (Idle rank): " << energy.read_oterm_energy + << " pJ" << endl; + cout << "WR Termination Energy (Idle rank): " << energy.write_oterm_energy + << " pJ" << endl; + } + } + cout << "ACT Stdby Energy: " << memArchSpec.nbrOfRanks * energy.act_stdby_energy << + " pJ" << endl; + cout << " Active Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_act << + " pJ" << endl; + cout << " Active Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_act_energy << + " pJ" << endl; + cout << " Active Stdby Energy during Auto-Refresh cycles in Self-Refresh" + << " Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_act_energy << + " pJ" << endl; + cout << "PRE Stdby Energy: " << memArchSpec.nbrOfRanks * energy.pre_stdby_energy << + " pJ" << endl; + cout << " Precharge Idle Energy: " << memArchSpec.nbrOfRanks * energy.idle_energy_pre << + " pJ" << endl; + cout << " Precharged Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.pup_pre_energy << + " pJ" << endl; + cout << " Precharge Stdby Energy during Auto-Refresh cycles " << + "in Self-Refresh Power-Up: " << memArchSpec.nbrOfRanks * energy.spup_ref_pre_energy << + " pJ" << endl; + cout << " Self-Refresh Power-Up Energy: " << memArchSpec.nbrOfRanks * energy.spup_energy << + " pJ" << endl; + cout << "Total Idle Energy (Active + Precharged): " << memArchSpec.nbrOfRanks * + (energy.idle_energy_act + energy.idle_energy_pre) << " pJ" << endl; + cout << "Total Power-Down Energy: " << memArchSpec.nbrOfRanks * (energy.f_act_pd_energy + + energy.f_pre_pd_energy + energy.s_act_pd_energy + energy.s_pre_pd_energy) << " pJ" << endl; + cout << " Fast-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks * + energy.f_act_pd_energy << " pJ" << endl; + cout << " Slow-Exit Active Power-Down Energy: " << memArchSpec.nbrOfRanks * + energy.s_act_pd_energy << " pJ" << endl; + cout << " Slow-Exit Active Power-Down Energy during Auto-Refresh cycles " + << "in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_act_energy << + " pJ" << endl; + cout << " Fast-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks * + energy.f_pre_pd_energy << " pJ" << endl; + cout << " Slow-Exit Precharged Power-Down Energy: " << memArchSpec.nbrOfRanks * + energy.s_pre_pd_energy << " pJ" << endl; + cout << " Slow-Exit Precharged Power-Down Energy during Auto-Refresh " << + "cycles in Self-Refresh: " << memArchSpec.nbrOfRanks * energy.sref_ref_pre_energy << + " pJ" << endl; + cout << "Auto-Refresh Energy: " << energy.ref_energy << " pJ" << endl; + cout << "Self-Refresh Energy: " << memArchSpec.nbrOfRanks * energy.sref_energy << + " pJ" << endl; + cout << "----------------------------------------" << endl; + cout << "Total Trace Energy: " << energy.total_energy << " pJ" << endl; + cout << "Average Power: " << power.average_power << " mW" << endl; + cout << "----------------------------------------" << endl; +} // MemoryPowerModel::power_print + +// Self-refresh active energy estimation (not including background energy) +double MemoryPowerModel::engy_sref(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 sref_energy; + + sref_energy = ((idd6 * sref_cycles) + ((idd5 - idd3n) * (sref_ref_act_cycles + + spup_ref_act_cycles + sref_ref_pre_cycles + spup_ref_pre_cycles))) + * vdd * clk; + return sref_energy; +} + +// IO and Termination power calculation based on Micron Power Calculators +// Absolute power measures are obtained from Micron Power Calculator (mentioned in mW) +void MemoryPowerModel::io_term_power(MemorySpecification memSpec) +{ + MemTimingSpec& memTimingSpec = memSpec.memTimingSpec; + MemArchitectureSpec& memArchSpec = memSpec.memArchSpec; + MemPowerSpec& memPowerSpec = memSpec.memPowerSpec; + + power.IO_power = memPowerSpec.ioPower; // in mW + power.WR_ODT_power = memPowerSpec.wrOdtPower; // in mW + + if (memArchSpec.nbrOfRanks > 1) { + power.TermRD_power = memPowerSpec.termRdPower; // in mW + power.TermWR_power = memPowerSpec.termWrPower; // in mW + } + + if (memPowerSpec.capacitance != 0.0) { + // If capacity is given, then IO Power depends on DRAM clock frequency. + power.IO_power = memPowerSpec.capacitance * 0.5 * pow(memPowerSpec.vdd2, 2.0) * memTimingSpec.clkMhz * 1000000; + } +} // MemoryPowerModel::io_term_power + + +double MemoryPowerModel::calcIoTermEnergy(int64_t cycles, double period, double power, int64_t numBits) const +{ + return static_cast<double>(cycles) * period * power * static_cast<double>(numBits); +} + +// time (t) * current (I) * voltage (V) energy calculation +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 new file mode 100644 index 000000000..b894f67dd --- /dev/null +++ b/ext/drampower/src/MemoryPowerModel.h @@ -0,0 +1,176 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar, Matthias Jung, Omar Naji + * + */ + +#ifndef MEMORY_POWER_MODEL_H +#define MEMORY_POWER_MODEL_H + +#include "MemorySpecification.h" +#include "CommandAnalysis.h" + +namespace Data { +class MemoryPowerModel { + public: + // Calculate energy and average power consumption for the given memory + // command trace + void power_calc(MemorySpecification memSpec, + const CommandAnalysis& counters, + int term); + + // Used to calculate self-refresh active energy + static double engy_sref(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); + + int64_t total_cycles; + + struct Energy { + // Total energy of all activates + double act_energy; + + // Total energy of all precharges + double pre_energy; + + // Total energy of all reads + double read_energy; + + // Total energy of all writes + double write_energy; + + // Total energy of all refreshes + double ref_energy; + + // Total background energy of all active standby cycles + double act_stdby_energy; + + // Total background energy of all precharge standby cycles + double pre_stdby_energy; + + // Total energy of idle cycles in the active mode + double idle_energy_act; + + // Total energy of idle cycles in the precharge mode + double idle_energy_pre; + + // Total trace/pattern energy + double total_energy; + + // Average Power + double average_power; + + // Energy consumed in active/precharged fast/slow-exit modes + double f_act_pd_energy; + double f_pre_pd_energy; + double s_act_pd_energy; + double s_pre_pd_energy; + + // Energy consumed in self-refresh mode + double sref_energy; + + // Energy consumed in auto-refresh during self-refresh mode + double sref_ref_energy; + double sref_ref_act_energy; + double sref_ref_pre_energy; + + // Energy consumed in powering-up from self-refresh mode + double spup_energy; + + // Energy consumed in auto-refresh during self-refresh power-up + double spup_ref_energy; + double spup_ref_act_energy; + double spup_ref_pre_energy; + + // Energy consumed in powering-up from active/precharged power-down modes + double pup_act_energy; + double pup_pre_energy; + + // Energy consumed by IO and Termination + double read_io_energy; // Read IO Energy + double write_term_energy; // Write Termination Energy + double read_oterm_energy; // Read Termination Energy from idle rank + double write_oterm_energy; // Write Termination Energy from idle rank + // Total IO and Termination Energy + double io_term_energy; + }; + + struct Power { + // Power measures corresponding to IO and Termination + double IO_power; // Read IO Power + double WR_ODT_power; // Write ODT Power + double TermRD_power; // Read Termination in idle rank (in dual-rank systems) + double TermWR_power; // Write Termination in idle rank (in dual-rank systems) + + // Average Power + double average_power; + }; + + // Print the power and energy + void power_print(MemorySpecification memSpec, + int term, + const CommandAnalysis& counters) const; + + // To derive IO and Termination Power measures using DRAM specification + void io_term_power(MemorySpecification memSpec); + + Energy energy; + Power power; + + private: + double calcIoTermEnergy(int64_t cycles, double period, double power, int64_t numBits) const; +}; + +class EnergyDomain { + public: + EnergyDomain(double voltage, double clkPeriod) : + voltage(voltage), + clkPeriod(clkPeriod) + {} + + double calcTivEnergy(int64_t cycles, double current) const; + private: + const double voltage; + const double clkPeriod; +}; + +} +#endif // ifndef MEMORY_POWER_MODEL_H diff --git a/ext/drampower/src/MemorySpecification.cc b/ext/drampower/src/MemorySpecification.cc new file mode 100644 index 000000000..3f9f18811 --- /dev/null +++ b/ext/drampower/src/MemorySpecification.cc @@ -0,0 +1,60 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#include "MemorySpecification.h" + +using namespace std; +using namespace Data; + +// Set variable values from XML +void MemorySpecification::processParameters() +{ + setVarFromParam(&id,"memoryId"); + memoryType = getParamValWithDefault("memoryType", string("DDR3")); + + if (hasParameter("memoryType")) { + memArchSpec.twoVoltageDomains = memoryType.hasTwoVoltageDomains(); + memArchSpec.dll = memoryType.hasDll(); + memArchSpec.termination = memoryType.hasTermination(); + + memPowerSpec.capacitance = memoryType.getCapacitance(); + memPowerSpec.ioPower = memoryType.getIoPower(); + memPowerSpec.wrOdtPower = memoryType.getWrOdtPower(); + memPowerSpec.termRdPower = memoryType.getTermRdPower(); + memPowerSpec.termWrPower = memoryType.getTermWrPower(); + } +} diff --git a/ext/drampower/src/MemorySpecification.h b/ext/drampower/src/MemorySpecification.h new file mode 100644 index 000000000..149d41c28 --- /dev/null +++ b/ext/drampower/src/MemorySpecification.h @@ -0,0 +1,239 @@ +/* + * 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. + * + * Authors: Karthik Chandrasekar + * + */ + +#ifndef TOOLS_MEMORY_SPECIFICATION_H +#define TOOLS_MEMORY_SPECIFICATION_H + +#include <cassert> +#include <string> + +#include "MemArchitectureSpec.h" +#include "MemTimingSpec.h" +#include "MemPowerSpec.h" +#include "Parametrisable.h" + + +namespace Data { +// Supported memory types +class MemoryType { + public: + enum MemoryType_t { + DDR2 = 0, + DDR3, + DDR4, + LPDDR, + LPDDR2, + LPDDR3, + WIDEIO_SDR, + MEMORY_TYPE_INVALID + }; + + MemoryType(MemoryType_t _val) : + val(_val) + { + } + + MemoryType() : + val(MEMORY_TYPE_INVALID) + { + } + + MemoryType(const std::string& _val) : + val(MEMORY_TYPE_INVALID) + { + if (_val == "DDR2") { + val = DDR2; + } else if (_val == "DDR3") { + val = DDR3; + } else if (_val == "DDR4") { + val = DDR4; + } else if (_val == "LPDDR") { + val = LPDDR; + } else if (_val == "LPDDR2") { + val = LPDDR2; + } else if (_val == "LPDDR3") { + val = LPDDR3; + } else if (_val == "WIDEIO_SDR") { + val = WIDEIO_SDR; + } + assert("Unknown memory type." && val != MEMORY_TYPE_INVALID); + } + + bool isLPDDRFamily() const + { + return val == LPDDR || + val == LPDDR2 || + val == LPDDR3 || + val == WIDEIO_SDR; + } + + bool hasTwoVoltageDomains() const + { + return val == LPDDR || + val == LPDDR2 || + val == LPDDR3 || + val == WIDEIO_SDR; + } + + bool isDDRFamily() const + { + return val == DDR2 || + val == DDR3 || + val == DDR4; + } + + bool hasDll() const + { + return val == DDR2 || + val == DDR3 || + val == DDR4; + } + + bool hasTermination() const + { + return val == DDR2 || + val == DDR3 || + val == DDR4; + } + + double getCapacitance() const + { + // LPDDR/2/3 and DDR memories only have IO Power (no ODT) + // Conservative estimates based on Micron Mobile LPDDR2 Power Calculator + // LPDDR/2/3 IO Capacitance in mF + if (val == LPDDR) { + return 0.0000000045; + } else if (val == LPDDR2) { + return 0.0000000025; + } else if (val == LPDDR3) { + return 0.0000000018; + } else { + return 0.0; + } + } + + double getIoPower() const + { + if (val == DDR2) { + // Conservative estimates based on Micron DDR2 Power Calculator + return 1.5; // in mW + } else if (val == DDR3) { + // Conservative estimates based on Micron DDR3 Power Calculator + return 4.6; // in mW + } else if (val == DDR4) { + // Conservative estimates based on Micron DDR3 Power Calculator + // using available termination resistance values from Micron DDR4 Datasheets + return 3.7; // in mW + } else { + return 0.0; + } + } + + double getWrOdtPower() const + { + if (val == DDR2) { + // Conservative estimates based on Micron DDR2 Power Calculator + return 8.2; // in mW + } else if (val == DDR3) { + // Conservative estimates based on Micron DDR3 Power Calculator + return 21.2; // in mW + } else if (val == DDR4) { + // Conservative estimates based on Micron DDR3 Power Calculator + // using available termination resistance values from Micron DDR4 Datasheets + return 17.0; // in mW + } else { + return 0.0; + } + } + + double getTermRdPower() const + { + if (val == DDR2) { + // Conservative estimates based on Micron DDR2 Power Calculator + return 13.1; // in mW + } else if (val == DDR3) { + // Conservative estimates based on Micron DDR3 Power Calculator + return 15.5; // in mW + } else if (val == DDR4) { + // Conservative estimates based on Micron DDR3 Power Calculator + // using available termination resistance values from Micron DDR4 Datasheets + return 12.4; // in mW + } else { + return 0.0; + } + } + + double getTermWrPower() const + { + if (val == DDR2) { + // Conservative estimates based on Micron DDR2 Power Calculator + return 14.6; // in mW + } else if (val == DDR3) { + // Conservative estimates based on Micron DDR3 Power Calculator + return 15.4; // in mW + } else if (val == DDR4) { + // Conservative estimates based on Micron DDR3 Power Calculator + // using available termination resistance values from Micron DDR4 Datasheets + return 12.3; // in mW + } else { + return 0.0; + } + } + + operator MemoryType_t() const { + return val; + } + + private: + MemoryType_t val; +}; + +class MemorySpecification : public virtual Parametrisable { + public: + std::string id; + MemoryType memoryType; + + MemArchitectureSpec memArchSpec; + MemTimingSpec memTimingSpec; + MemPowerSpec memPowerSpec; + + void processParameters(); + + static MemorySpecification getMemSpecFromXML(const std::string& id); +}; +} // namespace Data +#endif // ifndef TOOLS_MEMORY_SPECIFICATION_H diff --git a/ext/drampower/src/Parameter.cc b/ext/drampower/src/Parameter.cc new file mode 100644 index 000000000..9767e1c94 --- /dev/null +++ b/ext/drampower/src/Parameter.cc @@ -0,0 +1,121 @@ +/* + * 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. + * + * Authors: Andreas Hansson + * + */ + +#include "Parameter.h" + +#include <iomanip> +#include "Utils.h" + +using namespace Data; +using namespace std; + +Parameter::Parameter(const string& id, const string& type, + const string& value) : id(id), type(type), value(value) +{ +} + +string Parameter::getId() const +{ + return id; +} + +string Parameter::getType() const +{ + return type; +} + +int Parameter::getIntValue() const +{ + return fromString<int>(value); +} + +unsigned int Parameter::getUIntValue() const +{ + bool isHex = value.size() > 1 && value[0] == '0' && value[1] == 'x'; + + return fromString<unsigned int>(value, isHex ? std::hex : std::dec); +} + +#ifdef _LP64 + +size_t Parameter::getSizeTValue() const +{ + bool isHex = value.size() > 1 && value[0] == '0' && value[1] == 'x'; + + return fromString<size_t>(value, isHex ? std::hex : std::dec); +} + +#endif + +double Parameter::getDoubleValue() const +{ + return fromString<double>(value); +} + +bool Parameter::getBoolValue() const +{ + return fromString<bool>(value); +} + +string Parameter::getValue() const +{ + return value; +} + +Parameter Data::HexParameter(const string& id, int value) +{ + std::ostringstream ss; + + ss << "0x" << hex << setw(8) << setfill('0') << value; + + return Parameter(id, "int", ss.str()); +} + +Parameter Data::StringParameter(const string& id, const string& value) +{ + return Parameter(id, "string", value); +} + +ostream& Data::operator<<(ostream& os, const Parameter& parameter) +{ + os << "<parameter " << + "id=\"" << parameter.getId() << "\" " << + "type=\"" << parameter.getType() << "\" " + "value=\"" << parameter.getValue() << "\" />"; + + return os; +} diff --git a/ext/drampower/src/Parameter.h b/ext/drampower/src/Parameter.h new file mode 100644 index 000000000..2c9623eeb --- /dev/null +++ b/ext/drampower/src/Parameter.h @@ -0,0 +1,102 @@ +/* + * 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. + * + * Authors: Andreas Hansson + * + */ + +#ifndef DATA_PARAMETER_H +#define DATA_PARAMETER_H + +#include <string> +#include <ostream> + +namespace Data { +class Parameter { + public: + Parameter(const std::string& id, const std::string& type, + const std::string& value); + + std::string getId() const; + std::string getType() const; + std::string getValue() const; + + int getIntValue() const; + unsigned int getUIntValue() const; + size_t getSizeTValue() const; + double getDoubleValue() const; + bool getBoolValue() const; + + operator int() const { + return getIntValue(); + } + + operator unsigned int() const { + return getUIntValue(); + } + +#ifdef _LP64 + + operator size_t() const { + return getSizeTValue(); + } +#endif + + operator double() const { + return getDoubleValue(); + } + + operator bool() const { + return getBoolValue(); + } + + operator std::string() const { + return getValue(); + } + + private: + std::string id; + std::string type; + std::string value; +}; + +Parameter HexParameter(const std::string& id, + int value); + +Parameter StringParameter(const std::string& id, + const std::string& value); + +std::ostream& operator<<(std::ostream& os, + const Parameter& parameter); +} +#endif // ifndef DATA_PARAMETER_H diff --git a/ext/drampower/src/Parametrisable.cc b/ext/drampower/src/Parametrisable.cc new file mode 100644 index 000000000..a348fd86e --- /dev/null +++ b/ext/drampower/src/Parametrisable.cc @@ -0,0 +1,133 @@ +/* + * 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. + * + * Authors: Andreas Hansson + * + */ + +#include "Parametrisable.h" + +#include <iostream> +#include <cstdlib> + +using namespace Data; +using namespace std; + +void Parametrisable::pushParameter(const Parameter& parameter) +{ + parameters.push_back(parameter); +} + +void Parametrisable::setParameter(const Parameter& parameter, + unsigned int index) +{ + unsigned int count = 0; + + vector<Parameter>::iterator p = parameters.begin(); + + while (p != parameters.end() && !(p->getId() == parameter.getId() && + index == count)) { + if (p->getId() == parameter.getId()) + ++count; + ++p; + } + + if (p == parameters.end()) { + parameters.push_back(parameter); + } else { + p = parameters.erase(p); + parameters.insert(p, parameter); + } +} // Parametrisable::setParameter + +bool Parametrisable::removeParameter(const string& id, unsigned int index) +{ + unsigned int count = 0; + + for (vector<Parameter>::iterator p = parameters.begin(); + p != parameters.end(); ++p) { + if ((p->getId() == id) && (index == count++)) { + parameters.erase(p); + return true; + } + } + + return false; +} + +/** + * Get a parameter with a specific id. Should there be a multiplicity, + * then the index is used to determine which instance is returned, in + * order traversal. + */ +Parameter Parametrisable::getParameter(const string& id, + unsigned int index) const +{ + unsigned int count = 0; + + for (vector<Parameter>::const_iterator p = parameters.begin(); + p != parameters.end(); ++p) { + if ((p->getId() == id) && (index == count++)) { + return *p; + } + } + + cerr << "Could not find parameter '" << id << "' (" << index << ")" << endl; + cerr << "Stored parameters are: " << endl; + for (vector<Parameter>::const_iterator p = parameters.begin(); + p != parameters.end(); ++p) { + cerr << " " << p->getId() << ": " << p->getValue() << endl; + } + exit(1); + + return Parameter("", "", ""); +} // Parametrisable::getParameter + +vector<Parameter> Parametrisable::getParameters() const +{ + return parameters; +} + +bool Parametrisable::hasParameter(const string& id, unsigned int index) const +{ + unsigned int count = 0; + + for (vector<Parameter>::const_iterator p = parameters.begin(); + p != parameters.end(); ++p) { + if ((p->getId() == id) && (index == count++)) { + return true; + } + } + + return false; +} diff --git a/ext/drampower/src/Parametrisable.h b/ext/drampower/src/Parametrisable.h new file mode 100644 index 000000000..31a69190f --- /dev/null +++ b/ext/drampower/src/Parametrisable.h @@ -0,0 +1,136 @@ +/* + * 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. + * + * Authors: Andreas Hansson + * + */ + +#ifndef DATA_PARAMETRISABLE_H +#define DATA_PARAMETRISABLE_H + +#include <string> +#include <vector> + +#include "Parameter.h" + +namespace Data { +/** + * Convenience class for the architectural components that are + * parametrisable. The interface is shared and implemented only in + * this class. + */ +class Parametrisable { + public: + Parametrisable() + { + } + + virtual ~Parametrisable() + { + } + + /** + * Push a new parameter into the in-order vector without checking + * for duplicates. + */ + virtual void pushParameter(const Parameter& parameter); + + /** + * Set a parameter with a given index (default 0). This could for + * example be a queue size for a given channel id. + */ + void setParameter(const Parameter& parameter, + unsigned int index = 0); + + /** + * Get a parameter of a given name and of a certain index. Calling + * this method on an object that has no parameter of that name + * will result in application exit. + */ + Parameter getParameter(const std::string& id, + unsigned int index = 0) const; + + /** + * Remove a parameter with a specific name and index. If a parameter + * is removed this method returns true, otherwise false. + */ + bool removeParameter(const std::string& id, + unsigned int index = 0); + + /** + * Simply get all the parameters. + */ + std::vector<Parameter> getParameters() const; + + /** + * Check if a parameter of a certain name exists in the object. + */ + bool hasParameter(const std::string& id, + unsigned int index = 0) const; + + /** + * Convenience function to set a variable to the value stored in a parameter + * with built in error detection/assertion. Returns true if the value was + * successfully set. + * @param m + * @param paramName + * @param assertOnFail + * @return + */ + template<typename T> + bool setVarFromParam(T* m, const char* paramName) + { + if (hasParameter(paramName)) { + *m = static_cast<T>(getParameter(paramName)); + return true; + } else { + *m = static_cast<T>(0); + return false; + } + } + + template<typename T> + T getParamValWithDefault(const char* paramName, T defaultVal) const + { + if (hasParameter(paramName)) { + return static_cast<T>(getParameter(paramName)); + } else { + return defaultVal; + } + } + + protected: + std::vector<Parameter> parameters; +}; +} +#endif // ifndef DATA_PARAMETRISABLE_H diff --git a/ext/drampower/src/TraceParser.cc b/ext/drampower/src/TraceParser.cc new file mode 100644 index 000000000..ec87f06da --- /dev/null +++ b/ext/drampower/src/TraceParser.cc @@ -0,0 +1,120 @@ +/* + * 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. + * + * Authors: Omar Naji + * + */ +#include "TraceParser.h" + +#include "CommandAnalysis.h" +#include "CmdScheduler.h" + +using namespace Data; +using namespace std; + +Data::MemCommand TraceParser::parseLine(std::string line) +{ + MemCommand memcmd; + istringstream linestream(line); + string item; + double item_val; + unsigned itemnum = 0; + MemCommand::cmds type = MemCommand::NOP; // Initialized to prevent warning + + while (getline(linestream, item, ',')) { + if (itemnum == 0) { + stringstream timestamp(item); + timestamp >> item_val; + memcmd.setTime(item_val); + } else if (itemnum == 1) { + item_val = MemCommand::getTypeFromName(item); + memcmd.setType(static_cast<MemCommand::cmds>(item_val)); + } else if (itemnum == 2) { + stringstream bank(item); + bank >> item_val; + memcmd.setType(type); + memcmd.setBank(static_cast<unsigned>(item_val)); + } + type = memcmd.getType(); + itemnum++; + } + return memcmd; +} // TraceParser::parseLine + +void TraceParser::parseFile(MemorySpecification memSpec, std::ifstream& trace, + int window, int grouping, int interleaving, int burst, + int powerdown, int trans) +{ + ifstream pwr_trace; + + counters = CommandAnalysis(memSpec.memArchSpec.nbrOfBanks); + int nCommands = 0; + bool lastupdate = false; + if (trans) { + cmdScheduler cmdsched; + cmdsched.transTranslation(memSpec, trace, grouping, interleaving, burst, powerdown); + pwr_trace.open("commands.trace", ifstream::in); + std::string line; + while (getline(pwr_trace, line)) { + MemCommand cmdline = parseLine(line); + cmd_list.push_back(cmdline); + nCommands++; + if (nCommands == window) { + counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); + nCommands = 0; + cmd_list.clear(); + } + } + lastupdate = true; + counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); + cmd_list.clear(); + pwr_trace.close(); + } else { + std::string line; + while (getline(trace, line)) { + MemCommand cmdline = parseLine(line); + cmd_list.push_back(cmdline); + nCommands++; + if (nCommands == window) { + counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); + nCommands = 0; + cmd_list.clear(); + } + } + lastupdate = true; + counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmd_list, lastupdate); + cmd_list.clear(); + } + counters.clear(); + trace.close(); +} // TraceParser::parseFile diff --git a/ext/drampower/src/TraceParser.h b/ext/drampower/src/TraceParser.h new file mode 100644 index 000000000..cabfcd395 --- /dev/null +++ b/ext/drampower/src/TraceParser.h @@ -0,0 +1,70 @@ +/* + * 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. + * + * Authors: Omar Naji + * + */ + +#ifndef TRACE_PARSER_H +#define TRACE_PARSER_H + +#include <vector> +#include <string> + +#include "MemCommand.h" +#include "MemorySpecification.h" +#include "CommandAnalysis.h" + + +class TraceParser { + public: + // list of parsed commands + std::vector<Data::MemCommand> cmd_list; + + // function for parsing one line of the trace + Data::MemCommand parseLine(std::string line); + + Data::CommandAnalysis counters; + // function for parsing the whole file. + // use this function for small traces ( no out-of-memory issue ) + void parseFile(Data::MemorySpecification memSpec, + std::ifstream& trace, + int window, + int grouping, + int interleaving, + int burst, + int powerdown, + int trans); +}; + +#endif // ifndef TRACE_PARSER_H diff --git a/ext/drampower/src/Utils.h b/ext/drampower/src/Utils.h new file mode 100644 index 000000000..3fba0961f --- /dev/null +++ b/ext/drampower/src/Utils.h @@ -0,0 +1,64 @@ +/* + * 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. + * + * Authors: Andreas Hansson + * + */ + +#ifndef UTILS_H +#define UTILS_H + +#include <string> +#include <sstream> +#include <stdexcept> +#include <typeinfo> + +#define MILLION 1000000 + +template<typename T> +T fromString(const std::string& s, + std::ios_base& (*f)(std::ios_base &) = std::dec) +throw(std::runtime_error) +{ + std::istringstream is(s); + T t; + + if (!(is >> f >> t)) { + throw std::runtime_error("Cannot convert '" + s + "' to " + + typeid(t).name() + " using fromString"); + } + + return t; +} + +#endif /* UTILS_H */ diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.cc b/ext/drampower/src/libdrampower/LibDRAMPower.cc new file mode 100644 index 000000000..ac16f948b --- /dev/null +++ b/ext/drampower/src/libdrampower/LibDRAMPower.cc @@ -0,0 +1,83 @@ +/* + * 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. + * + * Authors: Matthias Jung, Omar Naji + * + */ + +#include "LibDRAMPower.h" + +using namespace Data; + +libDRAMPower::libDRAMPower(const MemorySpecification& memSpec, bool includeIoAndTermination) : + memSpec(memSpec), + counters(CommandAnalysis(memSpec.memArchSpec.nbrOfBanks)), + includeIoAndTermination(includeIoAndTermination) +{ +} + +libDRAMPower::~libDRAMPower() +{ +} + +void libDRAMPower::doCommand(MemCommand::cmds type, int bank, int64_t timestamp) +{ + MemCommand cmd(type, static_cast<unsigned>(bank), static_cast<double>(timestamp)); + cmdList.push_back(cmd); +} + +void libDRAMPower::updateCounters(bool lastUpdate) +{ + counters.getCommands(memSpec, memSpec.memArchSpec.nbrOfBanks, cmdList, lastUpdate); + cmdList.clear(); +} + +void libDRAMPower::calcEnergy() +{ + mpm.power_calc(memSpec, counters, includeIoAndTermination); +} + +void libDRAMPower::clearState() +{ + counters.clear(); +} + +const Data::MemoryPowerModel::Energy& libDRAMPower::getEnergy() const +{ + return mpm.energy; +} + +const Data::MemoryPowerModel::Power& libDRAMPower::getPower() const +{ + return mpm.power; +} diff --git a/ext/drampower/src/libdrampower/LibDRAMPower.h b/ext/drampower/src/libdrampower/LibDRAMPower.h new file mode 100644 index 000000000..9dea8b0f5 --- /dev/null +++ b/ext/drampower/src/libdrampower/LibDRAMPower.h @@ -0,0 +1,80 @@ +/* + * 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. + * + * Authors: Matthias Jung, Omar Naji + * + */ + +#ifndef LIB_DRAM_POWER_H +#define LIB_DRAM_POWER_H + +#include <stdint.h> +#include <vector> + +#include "CommandAnalysis.h" +#include "MemoryPowerModel.h" +#include "MemCommand.h" + +class libDRAMPower { + public: + libDRAMPower(const Data::MemorySpecification& memSpec, bool includeIoAndTermination); + ~libDRAMPower(); + + void doCommand(Data::MemCommand::cmds type, + int bank, + int64_t timestamp); + + void updateCounters(bool lastUpdate); + + void clearState(); + + void calcEnergy(); + + const Data::MemoryPowerModel::Energy& getEnergy() const; + const Data::MemoryPowerModel::Power& getPower() const; + + // list of all commands + std::vector<Data::MemCommand> cmdList; + private: + Data::MemorySpecification memSpec; + public: + Data::CommandAnalysis counters; + private: + bool includeIoAndTermination; + // Object of MemoryPowerModel which contains the results + // Energies(pJ) stored in energy, Powers(mW) stored in power. Number of + // each command stored in timings. + Data::MemoryPowerModel mpm; +}; + +#endif // ifndef LIB_DRAM_POWER_H diff --git a/ext/drampower/src/uncrustify.cfg b/ext/drampower/src/uncrustify.cfg new file mode 100644 index 000000000..ffe0e5f9c --- /dev/null +++ b/ext/drampower/src/uncrustify.cfg @@ -0,0 +1,280 @@ +tok_split_gte=false +utf8_byte=false +utf8_force=false +indent_cmt_with_tabs=false +indent_align_string=true +indent_braces=false +indent_braces_no_func=false +indent_braces_no_class=false +indent_braces_no_struct=false +indent_brace_parent=false +indent_namespace=false +indent_extern=false +indent_class=true +indent_class_colon=true +indent_else_if=false +indent_var_def_cont=false +indent_func_call_param=false +indent_func_def_param=false +indent_func_proto_param=false +indent_func_class_param=false +indent_func_ctor_var_param=false +indent_template_param=false +indent_func_param_double=false +indent_relative_single_line_comments=false +indent_col1_comment=true +indent_access_spec_body=false +indent_paren_nl=false +indent_comma_paren=false +indent_bool_paren=false +indent_first_bool_expr=false +indent_square_nl=false +indent_preserve_sql=false +indent_align_assign=true +sp_balance_nested_parens=false +align_keep_tabs=false +align_with_tabs=false +align_on_tabstop=false +align_number_left=true +align_func_params=true +align_same_func_call_params=true +align_var_def_colon=true +align_var_def_attribute=true +align_var_def_inline=true +align_right_cmt_mix=false +align_on_operator=true +align_mix_var_proto=false +align_single_line_func=true +align_single_line_brace=true +align_nl_cont=true +align_left_shift=true +align_oc_decl_colon=false +nl_collapse_empty_body=false +nl_assign_leave_one_liners=false +nl_class_leave_one_liners=false +nl_enum_leave_one_liners=false +nl_getset_leave_one_liners=false +nl_func_leave_one_liners=false +nl_if_leave_one_liners=false +nl_multi_line_cond=false +nl_multi_line_define=false +nl_before_case=true +nl_after_case=false +nl_after_return=true +nl_after_semicolon=true +nl_after_brace_open=false +nl_after_brace_open_cmt=false +nl_after_vbrace_open=false +nl_after_vbrace_open_empty=false +nl_after_brace_close=false +nl_after_vbrace_close=false +nl_define_macro=true +nl_squeeze_ifdef=false +nl_ds_struct_enum_cmt=true +nl_ds_struct_enum_close_brace=true +nl_create_if_one_liner=false +nl_create_for_one_liner=false +nl_create_while_one_liner=false +ls_for_split_full=false +ls_func_split_full=false +nl_after_multiline_comment=true +eat_blanks_after_open_brace=true +eat_blanks_before_close_brace=true +mod_full_brace_if_chain=true +mod_pawn_semicolon=false +mod_full_paren_if_bool=true +mod_remove_extra_semicolon=true +mod_sort_import=false +mod_sort_using=false +mod_sort_include=false +mod_move_case_break=true +mod_remove_empty_return=true +cmt_indent_multi=true +cmt_c_group=false +cmt_c_nl_start=false +cmt_c_nl_end=false +cmt_cpp_group=false +cmt_cpp_nl_start=false +cmt_cpp_nl_end=false +cmt_cpp_to_c=false +cmt_star_cont=false +cmt_multi_check_last=true +cmt_insert_before_preproc=false +pp_indent_at_level=false +pp_region_indent_code=false +pp_if_indent_code=false +pp_define_at_level=false +output_tab_size=2 +indent_columns=2 +indent_namespace_level=0 +indent_namespace_limit=0 +indent_access_spec=-1 +align_var_def_span=2 +align_var_def_star_style=0 +align_var_def_amp_style=0 +align_var_def_thresh=2 +align_var_def_gap=1 +align_assign_span=3 +align_assign_thresh=12 +align_enum_equ_span=1 +align_var_struct_span=1 +align_struct_init_span=1 +align_typedef_span=1 +align_typedef_star_style=2 +align_typedef_amp_style=2 +align_right_cmt_span=4 +align_right_cmt_at_col=1 +align_func_proto_span=1 +nl_end_of_file_min=1 +nl_func_var_def_blk=1 +nl_max=2 +nl_after_func_proto=0 +nl_after_func_body=2 +nl_after_func_body_class=2 +nl_after_func_body_one_liner=2 +nl_before_access_spec=2 +nl_after_access_spec=1 +nl_comment_func_def=1 +nl_after_try_catch_finally=1 +mod_full_brace_nl=1 +mod_add_long_function_closebrace_comment=16 +mod_add_long_switch_closebrace_comment=16 +mod_add_long_ifdef_endif_comment=16 +mod_add_long_ifdef_else_comment=16 +newlines=auto +indent_with_tabs=0 +sp_arith=add +sp_assign=add +sp_enum_assign=add +sp_pp_concat=add +sp_pp_stringify=add +sp_bool=add +sp_compare=add +sp_inside_paren=remove +sp_paren_paren=remove +sp_paren_brace=add +sp_before_ptr_star=remove +sp_before_unnamed_ptr_star=remove +sp_between_ptr_star=remove +sp_after_ptr_star=force +sp_after_ptr_star_func=force +sp_before_ptr_star_func=remove +sp_before_byref=remove +sp_before_unnamed_byref=remove +sp_after_byref=add +sp_after_byref_func=add +sp_before_byref_func=remove +sp_after_type=add +sp_before_angle=remove +sp_inside_angle=remove +sp_after_angle=remove +sp_angle_paren=remove +sp_angle_word=force +sp_before_sparen=force +sp_inside_sparen=remove +sp_after_sparen=remove +sp_sparen_brace=add +sp_special_semi=remove +sp_before_semi=remove +sp_before_semi_for=remove +sp_before_semi_for_empty=remove +sp_after_semi_for_empty=remove +sp_before_square=remove +sp_before_squares=remove +sp_inside_square=remove +sp_after_comma=add +sp_before_comma=remove +sp_after_class_colon=add +sp_before_class_colon=add +sp_before_case_colon=remove +sp_after_operator=remove +sp_after_operator_sym=remove +sp_after_cast=remove +sp_inside_paren_cast=remove +sp_cpp_cast_paren=remove +sp_sizeof_paren=remove +sp_inside_braces_enum=add +sp_inside_braces_struct=add +sp_inside_braces=add +sp_inside_braces_empty=remove +sp_type_func=add +sp_func_proto_paren=remove +sp_func_def_paren=remove +sp_inside_fparens=remove +sp_inside_fparen=remove +sp_square_fparen=remove +sp_fparen_brace=add +sp_func_call_paren=remove +sp_func_call_user_paren=remove +sp_func_class_paren=remove +sp_return_paren=add +sp_attribute_paren=remove +sp_defined_paren=remove +sp_throw_paren=remove +sp_macro=add +sp_macro_func=remove +sp_else_brace=add +sp_brace_else=add +sp_brace_typedef=add +sp_catch_brace=add +sp_brace_catch=add +sp_finally_brace=add +sp_brace_finally=add +sp_try_brace=add +sp_getset_brace=add +sp_before_dc=remove +sp_after_dc=remove +sp_not=remove +sp_inv=remove +sp_addr=remove +sp_member=remove +sp_deref=remove +sp_sign=remove +sp_incdec=remove +sp_before_nl_cont=remove +sp_after_oc_scope=remove +sp_after_oc_colon=remove +sp_before_oc_colon=remove +sp_after_send_oc_colon=add +sp_before_send_oc_colon=remove +sp_after_oc_type=remove +sp_cond_colon=add +sp_cond_question=add +sp_cmt_cpp_start=add +nl_start_of_file=remove +nl_end_of_file=force +nl_fcall_brace=force +nl_if_brace=remove +nl_brace_else=remove +nl_elseif_brace=remove +nl_else_brace=remove +nl_else_if=remove +nl_for_brace=remove +nl_while_brace=remove +nl_do_brace=remove +nl_switch_brace=remove +nl_namespace_brace=remove +nl_class_brace=remove +nl_class_init_args=add +nl_func_def_paren=remove +nl_func_decl_start=remove +nl_func_decl_args=add +nl_fdef_brace=force +nl_before_if=ignore +nl_after_if=ignore +nl_before_for=ignore +nl_after_for=ignore +nl_before_while=ignore +nl_after_while=ignore +nl_before_switch=ignore +nl_after_switch=ignore +nl_before_do=ignore +nl_after_do=ignore +mod_full_brace_do=force +mod_full_brace_for=force +mod_full_brace_function=force +mod_full_brace_if=force +mod_full_brace_while=force +mod_full_brace_using=remove +mod_paren_on_return=remove +pp_space=force |