diff --git a/DRAMSys/analyzer/scripts/plots.py b/DRAMSys/analyzer/scripts/plots.py index 6d9ddc21..c161140d 100755 --- a/DRAMSys/analyzer/scripts/plots.py +++ b/DRAMSys/analyzer/scripts/plots.py @@ -119,7 +119,7 @@ def power_window(connection, tracePath): for i in range(steps): result = cursor.fetchone() time[i] = float(result[0]) * 1000000000 # convertion of seconds to nanoseconds - power[i] = float(result[1]) / 1000000000 # conversion of pW to mW + power[i] = float(result[1]) # values are stored in mW name = ntpath.basename(tracePath) basename, extension = os.path.splitext(name) diff --git a/DRAMSys/simulator/simulator.pro b/DRAMSys/simulator/simulator.pro index 307a3ffc..2629ff42 100644 --- a/DRAMSys/simulator/simulator.pro +++ b/DRAMSys/simulator/simulator.pro @@ -49,13 +49,6 @@ INCLUDEPATH += src/common/third_party/DRAMPower/src/libdrampower DEFINES += TIXML_USE_STL DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES -release { - DEFINES += NDEBUG -} - -#CONFIG += c++11 -#QMAKE_CXXFLAGS += -O0 -g -#QMAKE_CXXFLAGS += -std=c++0x -O0 -g unix:!macx { QMAKE_CXXFLAGS += -std=c++11 -O0 -g diff --git a/DRAMSys/simulator/src/simulation/Dram.h b/DRAMSys/simulator/src/simulation/Dram.h index 62986456..8e025324 100644 --- a/DRAMSys/simulator/src/simulation/Dram.h +++ b/DRAMSys/simulator/src/simulation/Dram.h @@ -45,6 +45,7 @@ #include #include #include +#include #include "../common/DebugManager.h" #include "../common/dramExtension.h" #include "../controller/core/TimingCalculation.h" @@ -71,8 +72,7 @@ struct Dram : sc_module enum sc_time_unit pWindowUnit = Configuration::getInstance().PowerWindowUnit; sc_time powerWindowSize = sc_time(pWindowSize, pWindowUnit); libDRAMPower *DRAMPower; - double totalEnergy = 0; - double sumOfEnergyWindows = 0; + double sumOfEnergyWindows = 0.0; // Error Model related: ErrorStorageMode ErrorStoreMode = Configuration::getInstance().ErrorStoreMode; @@ -199,14 +199,13 @@ struct Dram : sc_module DRAMPower->updateCounters(true); DRAMPower->calcEnergy(); - double energy = sumOfEnergyWindows + DRAMPower->getEnergy().total_energy; - double averagePower = energy / sc_time_stamp().to_seconds(); + double totalEnergy = sumOfEnergyWindows + DRAMPower->getEnergy().total_energy; + // The energy is given in [pJ] and divided by [s] resulting in [pW] then converted to [mW] + double averagePower = (totalEnergy / sc_time_stamp().to_seconds()) / 1e9; - tlmRecorder->recordPower(sc_time_stamp().to_seconds(), averagePower); - - // Print Final Total Power Values - cout << name() << string("\tTotal Energy: \t") + to_string(energy) + string("\t[pJ]") << endl; - cout << name() << string("\tAverage Power: \t") + to_string(averagePower) + string("\t[pW]") << endl; + // Print the final total energy and the average power for the simulation + cout << name() << string("\tTotal Energy: \t") + to_string(totalEnergy) + string("\t[pJ]") << endl; + cout << name() << string("\tAverage Power: \t") + to_string(averagePower) + string("\t[mW]") << endl; } // Clean up: @@ -215,6 +214,14 @@ struct Dram : sc_module } } + // When working with floats, we have to decide ourselves what is an + // acceptable definition for "equal". Here the number is compared with a + // suitable error margin (0.00001). + bool is_equal(double a, double b, const double epsilon = 1e-05) + { + return std::fabs(a - b) < epsilon; + } + // This Thread is only triggered when Power Simulation is enabled. // It estimates the current average power which will be stored in the trace database for visualization purposes. void powerWindow() @@ -223,28 +230,45 @@ struct Dram : sc_module double currentTotalEnergy = 0; do { - unsigned long long c = sc_time_stamp().value() / Configuration::getInstance().memSpec.clk.value(); + // At the very beginning (zero clock cycles) the energy is 0, so we wait first + wait(powerWindowSize); - DRAMPower->doCommand(MemCommand::NOP, 0, c); + unsigned long long clk_cycles = sc_time_stamp().value() / Configuration::getInstance().memSpec.clk.value(); + + DRAMPower->doCommand(MemCommand::NOP, 0, clk_cycles); DRAMPower->updateCounters(false); DRAMPower->calcEnergy(); currentTotalEnergy = DRAMPower->getEnergy().total_energy; + currentAveragePower = DRAMPower->getPower().average_power; - assert(currentTotalEnergy != 0); + DRAMPower->clearCounters(clk_cycles); - DRAMPower->clearCounters(c); + // During operation the energy should never be zero since the device is always consuming + assert(!is_equal(currentTotalEnergy, 0.0)); + // Accumulate the energy since we are clearing the library + // counters. + // + // Here we use double values. The double type ensures 15 decimal + // digits to represent a number. It does not matter if the digits + // are before or after the comma. Thus we only have rounding for + // numbers represented with more than 15 decimal digits. + // + // In more technical terms: + // An IEEE double has 53 significant bits (see also DBL_MANT_DIG + // in ). That is approximately 15.95 decimal digits + // (log10(2^53)). The implementation sets the number of digits + // (DBL_DIG) to 15, not 16, because it has to round down. + // sumOfEnergyWindows += currentTotalEnergy; - // [pW] = [pJ] / [s] (here considering that DRAMPower provides the value always in pJ) - currentAveragePower = currentTotalEnergy / powerWindowSize.to_seconds(); + // Store the time (in seconds) and the current average power (in mW) into the database tlmRecorder->recordPower(sc_time_stamp().to_seconds(), currentAveragePower); + // Here considering that DRAMPower provides the energy in pJ and the power in mW printDebugMessage(string("\tCurrent Energy: \t") + to_string(currentTotalEnergy) + string("\t[pJ]")); - printDebugMessage(string("\tAverage Power: \t") + to_string(currentAveragePower) + string("\t[pW]")); - - wait(powerWindowSize); + printDebugMessage(string("\tAverage Power 1: \t") + to_string(currentAveragePower) + string("\t[mW]")); } while(true); }