Merge pull request #78 from fzeder/master
Power plots generation - scales fixed.
This commit is contained in:
61
DRAMSys/analyzer/scripts/plots.py
Normal file → Executable file
61
DRAMSys/analyzer/scripts/plots.py
Normal file → Executable file
@@ -7,6 +7,7 @@ import os
|
||||
|
||||
plots = []
|
||||
|
||||
|
||||
def plot(function):
|
||||
plots.append(function)
|
||||
return function
|
||||
@@ -21,48 +22,52 @@ def memory_utilisation_window(connection, tracePath):
|
||||
# Besides, extracting the data from the memory specs, it is feasible to calculate the maximum data rate of the memory and then determine the bandwidth in Gbit/s.
|
||||
# The bandwidth data are then plotted in two graphics.
|
||||
|
||||
steps = 1000
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(""" SELECT max(time) FROM Power """)
|
||||
maxTime = cursor.fetchone()
|
||||
cursor.execute(""" SELECT min(time) FROM Power where time > 0 """)
|
||||
windowSize = cursor.fetchone()[0]
|
||||
steps = ceil(float(maxTime[0])/float(windowSize))
|
||||
cursor.execute(""" SELECT max(DataStrobeEnd) FROM Transactions """)
|
||||
total = cursor.fetchone()
|
||||
windowSize = ceil(float(total[0])/float(steps))
|
||||
if (windowSize == 0):
|
||||
windowSize = 1
|
||||
# print(steps)
|
||||
# All possible cases of data transfers inside a time window
|
||||
queryFull = """ SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions Where DataStrobeBegin > ? and DataStrobeEnd < ?""" # The data transfer begins and ends inside the time window
|
||||
queryEnd = """ SELECT sum(DataStrobeEnd - ?) FROM transactions Where DataStrobeBegin < ? and DataStrobeEnd > ? and DataStrobeEnd <=?""" # Only the end of the data transfer is inside the time window
|
||||
queryBegin = """ SELECT sum(? - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeBegin < ? and DataStrobeEnd > ?""" # Only the beginning of the data transfer is inside the time window
|
||||
queryPart = """ SELECT DataStrobeBegin FROM transactions Where DataStrobeBegin <= ? and DataStrobeEnd >= ?""" # The data transfer occupies all the time window
|
||||
maxDataRate = maximum_data_rate(connection)
|
||||
bandwidthPercentage = [0] * (steps+1)
|
||||
bandwidth = [0] * (steps+1)
|
||||
bandwidthPercentage[0] = 0
|
||||
bandwidth[0] = 0
|
||||
# print(width)
|
||||
# print(clk)
|
||||
# print(rate)
|
||||
bandwidthPercentage = [0] * steps
|
||||
bandwidth = [0] * steps
|
||||
for i in range(steps):
|
||||
bandwidthPercentage[i+1] = 0
|
||||
# print(i)
|
||||
bandwidthPercentage[i] = 0
|
||||
cursor.execute(queryPart, (i*windowSize, (i+1)*windowSize))
|
||||
result = cursor.fetchone()
|
||||
if(result is None):
|
||||
cursor.execute(queryFull, (i*windowSize, (i+1)*windowSize))
|
||||
result = cursor.fetchone()
|
||||
if(result[0] is not None):
|
||||
bandwidthPercentage[i+1] += int(result[0])
|
||||
bandwidthPercentage[i] += int(result[0])
|
||||
# print(bandwidthPercentage[i])
|
||||
cursor.execute(queryEnd, (i*windowSize, i*windowSize, i*windowSize, (i+1)*windowSize))
|
||||
result = cursor.fetchone()
|
||||
if(result[0] is not None):
|
||||
bandwidthPercentage[i+1] += int(result[0])
|
||||
bandwidthPercentage[i] += int(result[0])
|
||||
# print(bandwidthPercentage[i])
|
||||
cursor.execute(queryBegin, ((i+1)*windowSize, i*windowSize, (i+1)*windowSize, (i+1)*windowSize))
|
||||
result = cursor.fetchone()
|
||||
if(result[0] is not None):
|
||||
bandwidthPercentage[i+1] += int(result[0])
|
||||
bandwidthPercentage[i] += int(result[0])
|
||||
# print(bandwidthPercentage[i])
|
||||
else:
|
||||
bandwidthPercentage[i+1] = windowSize
|
||||
bandwidthPercentage[i] = windowSize
|
||||
# print(bandwidthPercentage[i])
|
||||
bandwidthPercentage[i+1] = float(bandwidthPercentage[i+1]/windowSize)
|
||||
bandwidth[i+1] = float(bandwidthPercentage[i+1])*float(maxDataRate)/1024
|
||||
bandwidthPercentage[i+1] *= 100
|
||||
bandwidthPercentage[i] = float(bandwidthPercentage[i]/windowSize)
|
||||
bandwidth[i] = float(bandwidthPercentage[i])*float(maxDataRate)/1024
|
||||
bandwidthPercentage[i] *= 100
|
||||
|
||||
name = ntpath.basename(tracePath)
|
||||
basename, extension = os.path.splitext(name)
|
||||
@@ -74,7 +79,8 @@ def memory_utilisation_window(connection, tracePath):
|
||||
import numpy as np
|
||||
from matplotlib.backends.backend_pdf import PdfPages
|
||||
|
||||
time = np.arange(0, (steps+1)*windowSize, windowSize)
|
||||
time = np.arange(0, steps*windowSize, windowSize)
|
||||
|
||||
plt.figure()
|
||||
|
||||
subplotIndex = 211
|
||||
@@ -82,7 +88,7 @@ def memory_utilisation_window(connection, tracePath):
|
||||
plt.plot(time/1000, bandwidthPercentage)
|
||||
plt.xlabel('Time (ns)')
|
||||
plt.ylabel('Bandwidth (%)')
|
||||
plt.ylim(0, 120)
|
||||
plt.ylim(0, 100)
|
||||
plt.grid(True)
|
||||
|
||||
subplotIndex += 1
|
||||
@@ -104,16 +110,16 @@ def power_window(connection, tracePath):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute(""" SELECT max(time) FROM Power """)
|
||||
maxTime = cursor.fetchone()
|
||||
cursor.execute(""" SELECT min(time) FROM Power where time > 0 """)
|
||||
windowSize = cursor.fetchone()[0]
|
||||
steps = ceil(float(maxTime[0])/float(windowSize))
|
||||
cursor.execute(""" SELECT min(time) FROM Power WHERE time > 0""")
|
||||
windowSize = cursor.fetchone()
|
||||
steps = ceil(float(maxTime[0])/float(windowSize[0]))
|
||||
cursor.execute(""" SELECT * FROM Power """)
|
||||
time = [0] * (steps+1)
|
||||
power = [0] * (steps+1)
|
||||
for i in range((steps+1)):
|
||||
time = [0] * steps
|
||||
power = [0] * steps
|
||||
for i in range(steps):
|
||||
result = cursor.fetchone()
|
||||
time[i] = int(result[0])/1000
|
||||
power[i] = float(result[1])
|
||||
time[i] = float(result[0]) * 1000000000 # convertion of seconds to nanoseconds
|
||||
power[i] = float(result[1]) # values are stored in mW
|
||||
|
||||
name = ntpath.basename(tracePath)
|
||||
basename, extension = os.path.splitext(name)
|
||||
@@ -127,6 +133,7 @@ def power_window(connection, tracePath):
|
||||
plt.plot(time, power)
|
||||
plt.xlabel('Time (ns)')
|
||||
plt.ylabel('Power (mW)')
|
||||
plt.gca().set_ylim(bottom=0)
|
||||
plt.grid(True)
|
||||
pdf = PdfPages(OUTPUT_FILE)
|
||||
pdf.savefig()
|
||||
|
||||
@@ -26,7 +26,7 @@ CREATE TABLE GeneralInfo(
|
||||
);
|
||||
|
||||
CREATE TABLE Power(
|
||||
time INTEGER,
|
||||
time DOUBLE,
|
||||
AveragePower DOUBLE
|
||||
);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -74,10 +74,10 @@ TlmRecorder::~TlmRecorder()
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void TlmRecorder::recordPower(sc_time time, double averagePower)
|
||||
void TlmRecorder::recordPower(double timeInSeconds, double averagePower)
|
||||
{
|
||||
if (TlmRecorder::recordingEnabled) {
|
||||
sqlite3_bind_int64(insertPowerStatement, 1, time.value());
|
||||
sqlite3_bind_double(insertPowerStatement, 1, timeInSeconds);
|
||||
sqlite3_bind_double(insertPowerStatement, 2, averagePower);
|
||||
executeSqlStatement(insertPowerStatement);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public:
|
||||
void recordTracenames(string traces){this->traces = traces;}
|
||||
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordPower(sc_time time, double averagePower);
|
||||
void recordPower(double timeInSeconds, double averagePower);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <vector>
|
||||
#include <array>
|
||||
#include <cassert>
|
||||
#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;
|
||||
|
||||
// Bandwith realted:
|
||||
unsigned long long int numberOfTransactionsServed;
|
||||
@@ -96,7 +96,7 @@ struct Dram : sc_module
|
||||
if(powerAnalysis == true)
|
||||
{
|
||||
sc_time clk = Configuration::getInstance().memSpec.clk;
|
||||
|
||||
|
||||
MemArchitectureSpec memArchSpec;
|
||||
memArchSpec.burstLength = Configuration::getInstance().memSpec.BurstLength;
|
||||
memArchSpec.dataRate = Configuration::getInstance().memSpec.DataRate;
|
||||
@@ -169,7 +169,7 @@ struct Dram : sc_module
|
||||
memPowerSpec.vdd2 = Configuration::getInstance().memSpec.vDD2;
|
||||
|
||||
MemorySpecification memSpec;
|
||||
memSpec.memTimingSpec = memTimingSpec;
|
||||
memSpec.memTimingSpec = memTimingSpec;
|
||||
memSpec.memPowerSpec = memPowerSpec;
|
||||
memSpec.memArchSpec = memArchSpec;
|
||||
|
||||
@@ -204,27 +204,18 @@ struct Dram : sc_module
|
||||
|
||||
~Dram()
|
||||
{
|
||||
if(powerAnalysis == true)
|
||||
{
|
||||
if (powerAnalysis == true) {
|
||||
// Obtain the residual energy which was not covered by previous windows
|
||||
DRAMPower->updateCounters(true);
|
||||
DRAMPower->calcEnergy();
|
||||
|
||||
// Calculate the residual power and energy which was not covered by previous windows...
|
||||
printDebugMessage(string("\tCurrent Energy: \t") + to_string(DRAMPower->getEnergy().total_energy - totalEnergy));
|
||||
printDebugMessage(string("\tAverage Power: \t") + to_string((DRAMPower->getEnergy().total_energy - totalEnergy)/powerWindowSize.value()));
|
||||
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;
|
||||
|
||||
double currentTotalEnergy = DRAMPower->getEnergy().total_energy - totalEnergy;
|
||||
double currentAveragePower = currentTotalEnergy/powerWindowSize.value();
|
||||
sumOfEnergyWindows += currentTotalEnergy;
|
||||
tlmRecorder->recordPower(sc_time_stamp(),currentAveragePower);
|
||||
totalEnergy = DRAMPower->getEnergy().total_energy;
|
||||
|
||||
// Make sure that the summed energy of the windows is the same as the final value provided by DRAMPower:
|
||||
assert(sumOfEnergyWindows == totalEnergy);
|
||||
|
||||
// Print Final Total Power Values:
|
||||
cout << name() << string("\tTotal Energy: \t") + to_string(totalEnergy) << " pJ"<< endl;
|
||||
cout << name() << string("\tAverage Power: \t") + to_string(DRAMPower->getPower().average_power) << " mW"<< 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;
|
||||
}
|
||||
|
||||
// Bandwidth:
|
||||
@@ -238,9 +229,16 @@ struct Dram : sc_module
|
||||
for (auto e : ememory) {
|
||||
delete e;
|
||||
}
|
||||
//std::cout << "Simulated Memory Size: " << memory.size() << endl; // TODO Aufrauemen
|
||||
}
|
||||
|
||||
|
||||
// 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()
|
||||
@@ -248,22 +246,47 @@ struct Dram : sc_module
|
||||
double currentAveragePower = 0;
|
||||
double currentTotalEnergy = 0;
|
||||
|
||||
do
|
||||
{
|
||||
do {
|
||||
// At the very beginning (zero clock cycles) the energy is 0, so we wait first
|
||||
wait(powerWindowSize);
|
||||
|
||||
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 - totalEnergy;
|
||||
currentAveragePower = currentTotalEnergy/powerWindowSize.value();
|
||||
tlmRecorder->recordPower(sc_time_stamp(),currentAveragePower);
|
||||
totalEnergy = DRAMPower->getEnergy().total_energy;
|
||||
|
||||
currentTotalEnergy = DRAMPower->getEnergy().total_energy;
|
||||
currentAveragePower = DRAMPower->getPower().average_power;
|
||||
|
||||
DRAMPower->clearCounters(clk_cycles);
|
||||
|
||||
// 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 <cfloat>). 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;
|
||||
|
||||
printDebugMessage(string("\tCurrent Energy: \t") + to_string(currentTotalEnergy));
|
||||
printDebugMessage(string("\tAverage Power: \t") + to_string(currentAveragePower));
|
||||
wait(powerWindowSize);
|
||||
}
|
||||
while(true);
|
||||
// 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[mW]"));
|
||||
} while(true);
|
||||
}
|
||||
|
||||
virtual tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& payload, tlm::tlm_phase& phase, sc_time& delay)
|
||||
@@ -542,7 +565,7 @@ struct Dram : sc_module
|
||||
|
||||
void setTlmRecorder(TlmRecorder *rec)
|
||||
{
|
||||
tlmRecorder = rec;
|
||||
tlmRecorder = rec;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user