diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index 83d062c0..88056e7f 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -35,6 +35,7 @@ * Matthias Jung * Eder F. Zulian * Lukas Steiner + * Derek Christ */ #include @@ -306,10 +307,8 @@ void TlmRecorder::prepareSqlStatements() ":mcconfig, :memspec, :traces, :windowSize, :refreshMaxPostponed, :refreshMaxPulledin, :controllerThread, " ":maxBufferDepth, :per2BankOffset)"; - insertCommandLengthsString = - "INSERT INTO CommandLengths VALUES" - "(:NOP, :RD, :WR, :RDA, :WRA, :ACT, :PREPB, :REFPB, :RFMPB, :REFP2B, :RFMP2B, :PRESB, :REFSB, :RFMSB, " - ":PREAB, :REFAB, :RFMAB, :PDEA, :PDXA, :PDEP, :PDXP, :SREFEN, :SREFEX)"; + insertCommandLengthsString = "INSERT INTO CommandLengths VALUES" + "(:command, :length)"; insertDebugMessageString = "INSERT INTO DebugMessages (Time,Message) Values (:time,:message)"; @@ -376,31 +375,17 @@ void TlmRecorder::insertCommandLengths() { const MemSpec *memSpec = Configuration::getInstance().memSpec; - sqlite3_bind_int(insertCommandLengthsStatement, 1, static_cast(lround(memSpec->getCommandLength(Command::NOP) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 2, static_cast(lround(memSpec->getCommandLength(Command::RD) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 3, static_cast(lround(memSpec->getCommandLength(Command::WR) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 4, static_cast(lround(memSpec->getCommandLength(Command::RDA) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 5, static_cast(lround(memSpec->getCommandLength(Command::WRA) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 6, static_cast(lround(memSpec->getCommandLength(Command::ACT) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 7, static_cast(lround(memSpec->getCommandLength(Command::PREPB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 8, static_cast(lround(memSpec->getCommandLength(Command::REFPB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 9, static_cast(lround(memSpec->getCommandLength(Command::RFMPB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 10, static_cast(lround(memSpec->getCommandLength(Command::REFP2B) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 11, static_cast(lround(memSpec->getCommandLength(Command::RFMP2B) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 12, static_cast(lround(memSpec->getCommandLength(Command::PRESB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 13, static_cast(lround(memSpec->getCommandLength(Command::REFSB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 14, static_cast(lround(memSpec->getCommandLength(Command::RFMSB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 15, static_cast(lround(memSpec->getCommandLength(Command::PREAB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 16, static_cast(lround(memSpec->getCommandLength(Command::REFAB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 17, static_cast(lround(memSpec->getCommandLength(Command::RFMAB) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 18, static_cast(lround(memSpec->getCommandLength(Command::PDEA) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 19, static_cast(lround(memSpec->getCommandLength(Command::PDXA) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 20, static_cast(lround(memSpec->getCommandLength(Command::PDEP) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 21, static_cast(lround(memSpec->getCommandLength(Command::PDXP) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 22, static_cast(lround(memSpec->getCommandLength(Command::SREFEN) / memSpec->tCK))); - sqlite3_bind_int(insertCommandLengthsStatement, 23, static_cast(lround(memSpec->getCommandLength(Command::SREFEX) / memSpec->tCK))); + auto insertCommandLength = [this, memSpec](Command command) { + auto commandName = command.toString(); - executeSqlStatement(insertCommandLengthsStatement); + sqlite3_bind_text(insertCommandLengthsStatement, 1, commandName.c_str(), commandName.length(), nullptr); + sqlite3_bind_int(insertCommandLengthsStatement, 2, + static_cast(lround(memSpec->getCommandLength(command) / memSpec->tCK))); + executeSqlStatement(insertCommandLengthsStatement); + }; + + for (unsigned int command = 0; command < Command::END_ENUM; ++command) + insertCommandLength(static_cast(command)); } void TlmRecorder::insertTransactionInDB(Transaction &recordingData) diff --git a/DRAMSys/library/src/common/TlmRecorder.h b/DRAMSys/library/src/common/TlmRecorder.h index dabe3ec5..0d2ce1ad 100644 --- a/DRAMSys/library/src/common/TlmRecorder.h +++ b/DRAMSys/library/src/common/TlmRecorder.h @@ -35,6 +35,7 @@ * Matthias Jung * Eder F. Zulian * Lukas Steiner + * Derek Christ */ #ifndef TLMRECORDER_H @@ -153,123 +154,102 @@ private: insertBufferDepthString, insertBandwidthString; std::string initialCommand = - "DROP TABLE IF EXISTS Phases; \n" - "DROP TABLE IF EXISTS GeneralInfo; \n" - "DROP TABLE IF EXISTS CommandLengths; \n" - "DROP TABLE IF EXISTS Comments; \n" - "DROP TABLE IF EXISTS ranges; \n" - "DROP TABLE IF EXISTS Transactions; \n" - "DROP TABLE IF EXISTS DebugMessages; \n" - "DROP TABLE IF EXISTS Power; \n" - "DROP TABLE IF EXISTS BufferDepth; \n" - "DROP TABLE IF EXISTS Bandwidth; \n" - " \n" - "CREATE TABLE Phases( \n" - " ID INTEGER PRIMARY KEY, \n" - " PhaseName TEXT, \n" - " PhaseBegin INTEGER, \n" - " PhaseEnd INTEGER, \n" - " Transact INTEGER \n" - "); \n" - " \n" - "CREATE TABLE GeneralInfo( \n" - " NumberOfTransactions INTEGER, \n" - " TraceEnd INTEGER, \n" - " NumberOfRanks INTEGER, \n" - " NumberOfBankgroups INTEGER, \n" - " NumberOfBanks INTEGER, \n" - " clk INTEGER, \n" - " UnitOfTime TEXT, \n" - " MCconfig TEXT, \n" - " Memspec TEXT, \n" - " Traces TEXT, \n" - " WindowSize INTEGER, \n" - " RefreshMaxPostponed INTEGER, \n" - " RefreshMaxPulledin INTEGER, \n" - " ControllerThread INTEGER, \n" - " MaxBufferDepth INTEGER, \n" - " Per2BankOffset INTEGER \n" - "); \n" - " \n" - "CREATE TABLE CommandLengths( \n" - " NOP INTEGER, \n" - " RD INTEGER, \n" - " WR INTEGER, \n" - " RDA INTEGER, \n" - " WRA INTEGER, \n" - " ACT INTEGER, \n" - " PREPB INTEGER, \n" - " REFPB INTEGER, \n" - " RFMPB INTEGER, \n" - " REFP2B INTEGER, \n" - " RFMP2B INTEGER, \n" - " PRESB INTEGER, \n" - " REFSB INTEGER, \n" - " RFMSB INTEGER, \n" - " PREAB INTEGER, \n" - " REFAB INTEGER, \n" - " RFMAB INTEGER, \n" - " PDEA INTEGER, \n" - " PDXA INTEGER, \n" - " PDEP INTEGER, \n" - " PDXP INTEGER, \n" - " SREFEN INTEGER, \n" - " SREFEX INTEGER \n" - "); \n" - " \n" - "CREATE TABLE Power( \n" - " time DOUBLE, \n" - " AveragePower DOUBLE \n" - "); \n" - " \n" - "CREATE TABLE BufferDepth( \n" - " Time DOUBLE, \n" - " BufferNumber INTEGER, \n" - " AverageBufferDepth DOUBLE \n" - "); \n" - " \n" - "CREATE TABLE Bandwidth( \n" - " Time DOUBLE, \n" - " AverageBandwidth DOUBLE \n" - "); \n" - " \n" - "CREATE TABLE Comments( \n" - " Time INTEGER, \n" - " Text TEXT \n" - "); \n" - " \n" - "CREATE TABLE DebugMessages( \n" - " Time INTEGER, \n" - " Message TEXT \n" - "); \n" - " \n" - "-- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html)\n" - "CREATE VIRTUAL TABLE ranges USING rtree( \n" - " id, \n" - " begin, end \n" - "); \n" - " \n" - "CREATE TABLE Transactions( \n" - " ID INTEGER, \n" - " Range INTEGER, \n" - " Address INTEGER, \n" - " Burstlength INTEGER, \n" - " TThread INTEGER, \n" - " TChannel INTEGER, \n" - " TRank INTEGER, \n" - " TBankgroup INTEGER, \n" - " TBank INTEGER, \n" - " TRow INTEGER, \n" - " TColumn INTEGER, \n" - " DataStrobeBegin INTEGER, \n" - " DataStrobeEnd INTEGER, \n" - " TimeOfGeneration INTEGER, \n" - " Command TEXT \n" - "); \n" - " \n" - "CREATE INDEX ranges_index ON Transactions(Range); \n" - "CREATE INDEX \"phasesTransactions\" ON \"Phases\" (\"Transact\" ASC); \n" - "CREATE INDEX \"messageTimes\" ON \"DebugMessages\" (\"Time\" ASC); \n"; + "DROP TABLE IF EXISTS Phases; \n" + "DROP TABLE IF EXISTS GeneralInfo; \n" + "DROP TABLE IF EXISTS CommandLengths; \n" + "DROP TABLE IF EXISTS Comments; \n" + "DROP TABLE IF EXISTS ranges; \n" + "DROP TABLE IF EXISTS Transactions; \n" + "DROP TABLE IF EXISTS DebugMessages; \n" + "DROP TABLE IF EXISTS Power; \n" + "DROP TABLE IF EXISTS BufferDepth; \n" + "DROP TABLE IF EXISTS Bandwidth; \n" + " \n" + "CREATE TABLE Phases( \n" + " ID INTEGER PRIMARY KEY, \n" + " PhaseName TEXT, \n" + " PhaseBegin INTEGER, \n" + " PhaseEnd INTEGER, \n" + " Transact INTEGER \n" + "); \n" + " \n" + "CREATE TABLE GeneralInfo( \n" + " NumberOfTransactions INTEGER, \n" + " TraceEnd INTEGER, \n" + " NumberOfRanks INTEGER, \n" + " NumberOfBankgroups INTEGER, \n" + " NumberOfBanks INTEGER, \n" + " clk INTEGER, \n" + " UnitOfTime TEXT, \n" + " MCconfig TEXT, \n" + " Memspec TEXT, \n" + " Traces TEXT, \n" + " WindowSize INTEGER, \n" + " RefreshMaxPostponed INTEGER, \n" + " RefreshMaxPulledin INTEGER, \n" + " ControllerThread INTEGER, \n" + " MaxBufferDepth INTEGER, \n" + " Per2BankOffset INTEGER \n" + "); \n" + " \n" + "CREATE TABLE CommandLengths( \n" + " Command TEXT, \n" + " Length INTEGER \n" + "); \n" + " \n" + "CREATE TABLE Power( \n" + " time DOUBLE, \n" + " AveragePower DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE BufferDepth( \n" + " Time DOUBLE, \n" + " BufferNumber INTEGER, \n" + " AverageBufferDepth DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE Bandwidth( \n" + " Time DOUBLE, \n" + " AverageBandwidth DOUBLE \n" + "); \n" + " \n" + "CREATE TABLE Comments( \n" + " Time INTEGER, \n" + " Text TEXT \n" + "); \n" + " \n" + "CREATE TABLE DebugMessages( \n" + " Time INTEGER, \n" + " Message TEXT \n" + "); \n" + " \n" + "-- use SQLITE R* TREE Module to make queries on timespans effecient (see http://www.sqlite.org/rtree.html)\n" + "CREATE VIRTUAL TABLE ranges USING rtree( \n" + " id, \n" + " begin, end \n" + "); \n" + " \n" + "CREATE TABLE Transactions( \n" + " ID INTEGER, \n" + " Range INTEGER, \n" + " Address INTEGER, \n" + " Burstlength INTEGER, \n" + " TThread INTEGER, \n" + " TChannel INTEGER, \n" + " TRank INTEGER, \n" + " TBankgroup INTEGER, \n" + " TBank INTEGER, \n" + " TRow INTEGER, \n" + " TColumn INTEGER, \n" + " DataStrobeBegin INTEGER, \n" + " DataStrobeEnd INTEGER, \n" + " TimeOfGeneration INTEGER, \n" + " Command TEXT \n" + "); \n" + " \n" + "CREATE INDEX ranges_index ON Transactions(Range); \n" + "CREATE INDEX \"phasesTransactions\" ON \"Phases\" (\"Transact\" ASC); \n" + "CREATE INDEX \"messageTimes\" ON \"DebugMessages\" (\"Time\" ASC); \n"; }; #endif // TLMRECORDER_H diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h index ce474fe8..cca1cf9a 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h @@ -116,7 +116,7 @@ protected: friend class PhaseDependency; }; -class REQ : public Phase +class REQ final : public Phase { public: using Phase::Phase; @@ -136,8 +136,7 @@ protected: } }; - -class RESP : public Phase +class RESP final : public Phase { public: using Phase::Phase; @@ -158,7 +157,7 @@ protected: }; /* -class PREB: public Phase +class PREB final : public Phase { public: using Phase::Phase; @@ -173,7 +172,7 @@ protected: } }; */ -class PREPB : public Phase +class PREPB final : public Phase { public: using Phase::Phase; @@ -188,7 +187,7 @@ protected: } }; -class PRESB : public Phase +class PRESB final : public Phase { public: using Phase::Phase; @@ -216,7 +215,7 @@ protected: } }; -class PREAB : public Phase +class PREAB final : public Phase { public: using Phase::Phase; @@ -244,7 +243,7 @@ protected: } }; /* -class ACTB : public Phase +class ACTB final : public Phase { public: using Phase::Phase; @@ -259,7 +258,7 @@ protected: } }; */ -class ACT : public Phase +class ACT final : public Phase { public: using Phase::Phase; @@ -274,7 +273,7 @@ protected: } }; -class RD : public Phase +class RD final : public Phase { public: using Phase::Phase; @@ -289,7 +288,7 @@ protected: } }; -class RDA : public Phase +class RDA final : public Phase { public: using Phase::Phase; @@ -304,7 +303,7 @@ protected: } }; -class WR : public Phase +class WR final : public Phase { public: using Phase::Phase; @@ -319,7 +318,7 @@ protected: } }; -class WRA : public Phase +class WRA final : public Phase { public: using Phase::Phase; @@ -360,7 +359,7 @@ protected: } }; -class REFAB : public AUTO_REFRESH +class REFAB final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -375,7 +374,7 @@ protected: } }; -class RFMAB : public AUTO_REFRESH +class RFMAB final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -396,8 +395,7 @@ protected: } }; - -class REFPB : public AUTO_REFRESH +class REFPB final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -408,7 +406,7 @@ protected: } }; -class REFP2B : public AUTO_REFRESH +class REFP2B final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -423,7 +421,7 @@ protected: } }; -class RFMP2B : public AUTO_REFRESH +class RFMP2B final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -444,7 +442,7 @@ protected: } }; -class REFSB : public AUTO_REFRESH +class REFSB final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -459,7 +457,7 @@ protected: } }; -class RFMSB : public AUTO_REFRESH +class RFMSB final : public AUTO_REFRESH { public: using AUTO_REFRESH::AUTO_REFRESH; @@ -484,6 +482,8 @@ class PDNAB : public Phase { public: using Phase::Phase; + virtual ~PDNAB() = default; + protected: QString Name() const override { @@ -508,7 +508,7 @@ protected: } }; -class PDNA : public PDNAB +class PDNA final : public PDNAB { public: using PDNAB::PDNAB; @@ -527,6 +527,8 @@ class PDNPB : public Phase { public: using Phase::Phase; + virtual ~PDNPB() = default; + protected: QString Name() const override { @@ -551,7 +553,7 @@ protected: } }; -class PDNP : public PDNPB +class PDNP final : public PDNPB { public: using PDNPB::PDNPB; @@ -570,6 +572,8 @@ class SREFB : public Phase { public: using Phase::Phase; + virtual ~SREFB() = default; + protected: QString Name() const override { diff --git a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.cpp b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.cpp index b99f3141..741295a3 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.cpp @@ -45,8 +45,6 @@ #include #include -using namespace std; - PythonCaller &PythonCaller::instance() { static PythonCaller instance; @@ -98,21 +96,20 @@ PythonCaller::PythonCaller() : //returns new reference to the function (see: http://edcjones.tripod.com/refcount.html for the difference between "new reference" and "borrowed reference") -PyObject *PythonCaller::loadFunctionFromModule(string moduleName, - string functionName) +PyObject *PythonCaller::loadFunctionFromModule(std::string moduleName, std::string functionName) { PyObject *pModuleName = PyUnicode_FromString(moduleName.c_str()); PyObject *pModule = PyImport_Import(pModuleName); if (!pModule) { - throw runtime_error(string("Could not load module " + moduleName)); + throw std::runtime_error(std::string("Could not load module " + moduleName)); } PyObject *pFunction = PyObject_GetAttrString(pModule, functionName.c_str()); if (!pFunction || !PyCallable_Check(pFunction)) { - throw runtime_error(string("Could not load test function " + functionName + - "in module " + moduleName)); + throw std::runtime_error( + std::string("Could not load test function " + functionName + "in module " + moduleName)); } Py_DECREF(pModuleName); @@ -134,8 +131,7 @@ PythonCaller::~PythonCaller() Py_Finalize(); } -PyObject *PythonCaller::callMetricsFunction(PyObject *function, - QString argument, vector list) +PyObject *PythonCaller::callMetricsFunction(PyObject *function, QString argument, std::vector list) { assert(PyCallable_Check(function)); @@ -153,8 +149,7 @@ PyObject *PythonCaller::callMetricsFunction(PyObject *function, if (!pResult) { PyErr_Print(); - throw runtime_error(string("Error in calling " + testFunctionName + - " in module " + testModuleName)); + throw std::runtime_error(std::string("Error in calling " + testFunctionName + " in module " + testModuleName)); } return pResult; @@ -174,8 +169,7 @@ PyObject *PythonCaller::callFunctionWithStringArgument(PyObject *function, if (!pResult) { PyErr_Print(); - throw runtime_error(string("Error in calling " + testFunctionName + - " in module " + testModuleName)); + throw std::runtime_error(std::string("Error in calling " + testFunctionName + " in module " + testModuleName)); } return pResult; @@ -188,7 +182,7 @@ PyObject *PythonCaller::callFunctionWithoutArguments(PyObject *function) if (!pResult) { PyErr_Print(); - throw runtime_error(string("Error in calling python function")); + throw std::runtime_error(std::string("Error in calling python function")); } return pResult; @@ -212,8 +206,7 @@ TraceTestResults PythonCaller::runTestsOnTrace(QString pathToTrace) return traceTestResult; } -TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace( - QString pathToTrace, vector list) +TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace, std::vector list) { TraceCalculatedMetrics result(QFileInfo(pathToTrace).baseName()); PyObject *pResult = callMetricsFunction(pCalculateMetricsFunction, pathToTrace, @@ -230,9 +223,9 @@ TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace( return result; } -vector PythonCaller::getMetrics(QString pathToTrace) +std::vector PythonCaller::getMetrics(QString pathToTrace) { - vector result; + std::vector result; PyObject *pResult = callFunctionWithStringArgument(pGetMetricsFunction, pathToTrace); diff --git a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h index 0f843189..eeb04d7e 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h +++ b/DRAMSys/traceAnalyzer/businessObjects/pythoncaller.h @@ -56,7 +56,6 @@ class PythonCaller { public: static PythonCaller &instance(); - PythonCaller(const PythonCaller &other) = delete; TraceTestResults runTestsOnTrace(QString pathToTrace); TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace, @@ -70,6 +69,8 @@ public: private: PythonCaller(); ~PythonCaller(); + PythonCaller(const PythonCaller &other) = delete; + PythonCaller &operator=(const PythonCaller &other) = delete; PyObject *pRunTestsFunction, *pCalculateMetricsFunction, *pGetMetricsFunction; PyObject *pGenPlotsFunction; diff --git a/DRAMSys/traceAnalyzer/data/tracedb.cpp b/DRAMSys/traceAnalyzer/data/tracedb.cpp index 5564d843..6d79a2c8 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.cpp +++ b/DRAMSys/traceAnalyzer/data/tracedb.cpp @@ -334,101 +334,80 @@ GeneralInfo TraceDB::getGeneralInfoFromDB() CommandLengths TraceDB::getCommandLengthsFromDB() { - QVariant parameter; - parameter = getParameterFromTable("NOP", "CommandLengths"); - unsigned NOP = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("RD", "CommandLengths"); - unsigned RD = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("WR", "CommandLengths"); - unsigned WR = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("RDA", "CommandLengths"); - unsigned RDA = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("WRA", "CommandLengths"); - unsigned WRA = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("ACT", "CommandLengths"); - unsigned ACT = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PREPB", "CommandLengths"); - unsigned PREPB; - if (parameter.isValid()) + const std::string table = "CommandLengths"; + + auto getLengthFromDb = [=, &table](const std::string &command) -> QVariant { - PREPB = parameter.toUInt(); - } - else - { - parameter = getParameterFromTable("PRE", "CommandLengths"); - if (parameter.isValid()) - PREPB = parameter.toUInt(); + QSqlQuery query(("SELECT Length FROM " + table + " WHERE Command = \"" + command + "\"").c_str(), database); + + if (query.first()) + return query.value(0); else - PREPB = 1; - } - parameter = getParameterFromTable("REFPB", "CommandLengths"); - unsigned REFPB; - if (parameter.isValid()) + return {}; + }; + + auto getCommandLength = [=, &table](const std::string &command) -> unsigned { - REFPB = parameter.toUInt(); - } - else - { - parameter = getParameterFromTable("REFB", "CommandLengths"); - if (parameter.isValid()) - REFPB = parameter.toUInt(); + QVariant length = getLengthFromDb(command); + + if (length.isValid()) + return length.toUInt(); else - REFPB = 1; - } - parameter = getParameterFromTable("RFMPB", "CommandLengths"); - unsigned RFMPB = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("REFP2B", "CommandLengths"); - unsigned REFP2B = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("RFMP2B", "CommandLengths"); - unsigned RFMP2B = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PRESB", "CommandLengths"); - unsigned PRESB = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("REFSB", "CommandLengths"); - unsigned REFSB = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("RFMSB", "CommandLengths"); - unsigned RFMSB = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PREAB", "CommandLengths"); - unsigned PREAB; - if (parameter.isValid()) + { + qDebug() << "CommandLength for" << command.c_str() << "not present in table" << table.c_str() + << ". Defaulting to 1."; + return 1; + } + }; + + auto getCommandLengthOrElse = [=, &table](const std::string &command, const std::string &elseCommand) -> unsigned { - PREAB = parameter.toUInt(); - } - else - { - parameter = getParameterFromTable("PREA", "CommandLengths"); - if (parameter.isValid()) - PREAB = parameter.toUInt(); + QVariant length = getLengthFromDb(command); + + if (length.isValid()) + return length.toUInt(); else - PREAB = 1; - } - parameter = getParameterFromTable("REFAB", "CommandLengths"); - unsigned REFAB; - if (parameter.isValid()) - { - REFAB = parameter.toUInt(); - } - else - { - parameter = getParameterFromTable("REFA", "CommandLengths"); - if (parameter.isValid()) - REFAB = parameter.toUInt(); - else - REFAB = 1; - } - parameter = getParameterFromTable("RFMAB", "CommandLengths"); - unsigned RFMAB = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PDEA", "CommandLengths"); - unsigned PDEA = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PDXA", "CommandLengths"); - unsigned PDXA = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PDEP", "CommandLengths"); - unsigned PDEP = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("PDXP", "CommandLengths"); - unsigned PDXP = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("SREFEN", "CommandLengths"); - unsigned SREFEN = parameter.isValid() ? parameter.toUInt() : 1; - parameter = getParameterFromTable("SREFEX", "CommandLengths"); - unsigned SREFEX = parameter.isValid() ? parameter.toUInt() : 1; + { + length = getLengthFromDb(command); + + if (length.isValid()) + return length.toUInt(); + else + { + qDebug() << "CommandLength for" << command.c_str() << "and" << elseCommand.c_str() + << "not present in table" << table.c_str() << ". Defaulting to 1."; + return 1; + } + } + }; + + unsigned NOP = getCommandLength("NOP"); + unsigned RD = getCommandLength("RD"); + unsigned WR = getCommandLength("RD"); + unsigned RDA = getCommandLength("RDA"); + unsigned WRA = getCommandLength("WRA"); + unsigned ACT = getCommandLength("ACT"); + + unsigned PREPB = getCommandLengthOrElse("PREPB", "PRE"); + unsigned REFPB = getCommandLengthOrElse("REFPB", "REFB"); + + unsigned RFMPB = getCommandLength("RFMPB"); + unsigned REFP2B = getCommandLength("REFP2B"); + unsigned RFMP2B = getCommandLength("RFMP2B"); + unsigned PRESB = getCommandLength("PRESB"); + unsigned REFSB = getCommandLength("REFSB"); + unsigned RFMSB = getCommandLength("RFMSB"); + + unsigned PREAB = getCommandLengthOrElse("PREAB", "PREA"); + unsigned REFAB = getCommandLengthOrElse("REFAB", "REFA"); + + unsigned RFMAB = getCommandLength("RFMAB"); + unsigned PDEA = getCommandLength("PDEA"); + unsigned PDXA = getCommandLength("PDXA"); + unsigned PDEP = getCommandLength("PDEP"); + unsigned PDXP = getCommandLength("PDXP"); + unsigned SREFEN = getCommandLength("SREFEN"); + unsigned SREFEX = getCommandLength("SREFEX"); return {NOP, RD, WR, RDA, WRA, ACT, PREPB, REFPB, RFMPB, REFP2B, RFMP2B, PRESB, REFSB, RFMSB, PREAB, REFAB, RFMAB, PDEA, PDXA, PDEP, PDXP, SREFEN, SREFEX}; diff --git a/DRAMSys/traceAnalyzer/data/tracedb.h b/DRAMSys/traceAnalyzer/data/tracedb.h index 8b759f24..0ee3e3cb 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.h +++ b/DRAMSys/traceAnalyzer/data/tracedb.h @@ -115,7 +115,7 @@ private: QString pathToDB; QSqlDatabase database; GeneralInfo generalInfo; - CommandLengths commandLengths{}; + CommandLengths commandLengths; QSqlQuery insertPhaseQuery; QSqlQuery insertTransactionQuery; diff --git a/DRAMSys/traceAnalyzer/scripts/memUtil.py b/DRAMSys/traceAnalyzer/scripts/memUtil.py index ce928d4d..102f3abf 100755 --- a/DRAMSys/traceAnalyzer/scripts/memUtil.py +++ b/DRAMSys/traceAnalyzer/scripts/memUtil.py @@ -54,6 +54,12 @@ def getNumberOfTransactions(dbconnection): result = cursor.fetchone() return result[0] +def getTraceEndTime(dbconnection): + cursor = dbconnection.cursor() + cursor.execute("SELECT TraceEnd FROM GeneralInfo") + result = cursor.fetchone() + return result[0] + def getNumberOfBanks(dbconnection): cursor = dbconnection.cursor() cursor.execute("SELECT NumberOfBanks FROM generalInfo") diff --git a/DRAMSys/traceAnalyzer/scripts/metrics.py b/DRAMSys/traceAnalyzer/scripts/metrics.py index 303626f1..4d05186e 100644 --- a/DRAMSys/traceAnalyzer/scripts/metrics.py +++ b/DRAMSys/traceAnalyzer/scripts/metrics.py @@ -1,5 +1,6 @@ import sys import sqlite3 +import argparse from memUtil import * from math import * @@ -35,6 +36,27 @@ def trace_length_in_ns(connection): result = cursor.fetchone() return result[0] +@metric +def command_bus_utilisation_in_percent(connection): + cursor = connection.cursor() + cursor.execute(""" + SELECT + SUM(CommandLengths.Length) + FROM + Phases + INNER JOIN + CommandLengths + ON Phases.PhaseName = CommandLengths.Command + """) + result = cursor.fetchone()[0] + + if (result is None): + result = 0 + + clk, _ = getClock(connection) + traceEnd = getTraceEndTime(connection) + cmdBusOccupied = result * clk + return cmdBusOccupied / traceEnd * 100 @metric def average_response_latency_in_ns(connection): @@ -44,11 +66,94 @@ def average_response_latency_in_ns(connection): result = cursor.fetchone() return round(result[0], 1) +@metric +def average_rd_response_latency_in_ns(connection): + cursor = connection.cursor() + cursor.execute(""" + SELECT + AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND Transactions.Command = "R" + """) + result = cursor.fetchone() + return round(result[0], 1) + +@metric +def average_wr_response_latency_in_ns(connection): + cursor = connection.cursor() + cursor.execute(""" + SELECT + AVG(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND Transactions.Command = "W" + """) + result = cursor.fetchone() + return round(result[0], 1) + +@metric +def max_rd_response_latency_in_ns(connection): + cursor = connection.cursor() + cursor.execute(""" + SELECT + max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND Transactions.Command = "R" + """) + result = cursor.fetchone() + return round(result[0], 1) + +@metric +def max_wr_response_latency_in_ns(connection): + cursor = connection.cursor() + cursor.execute(""" + SELECT + max(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND Transactions.Command = "W" + """) + result = cursor.fetchone() + return round(result[0], 1) @metric def max_response_latency_in_ns(connection): cursor = connection.cursor() - cursor.execute(""" SELECT max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP + cursor.execute(""" SELECT max(RESP.PHASEBEGIN - REQ.PHASEBEGIN)/1000 FROM PHASES REQ, PHASES RESP WHERE REQ.PHASENAME = 'REQ' AND RESP.PHASENAME='RESP' AND REQ.TRANSACT = RESP.TRANSACT """) result = cursor.fetchone() return result[0] @@ -995,8 +1100,6 @@ def calculateMetricsFromFuncs(pathToTrace, selectedMetrics): connection.close() return calculatedMetrics -import argparse - if __name__ == "__main__": """ Only non-threaded metrics are implemented for selection through command line diff --git a/DRAMSys/traceAnalyzer/scripts/plots.py b/DRAMSys/traceAnalyzer/scripts/plots.py index e3c469a0..6b564ffe 100755 --- a/DRAMSys/traceAnalyzer/scripts/plots.py +++ b/DRAMSys/traceAnalyzer/scripts/plots.py @@ -1,14 +1,21 @@ import sys import sqlite3 -from memUtil import * -from math import * import ntpath import os +import matplotlib.pyplot as plt +import numpy as np +from memUtil import * +from math import * +from matplotlib.backends.backend_pdf import PdfPages + numberOfBins = "auto" latencyRange = None plots = [] +def plot(function): + plots.append(function) + return function def getThreads(connection): cursor = connection.cursor() @@ -77,11 +84,57 @@ def calculate_bandwidth_util(connection, windowSize, steps, queryFull, queryEnd, def memory_utilisation_window_thread(connection, tracePath, steps, thread_ID): - # All possible cases of data transfers inside a time window - queryFull = """ SELECT sum(DataStrobeEnd - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeEnd <= ? and TThread = {0}""" # The data transfer begins and ends inside the time window - queryEnd = """ SELECT sum(DataStrobeEnd - ?) FROM transactions Where DataStrobeBegin < ? and DataStrobeEnd > ? and DataStrobeEnd <=? and TThread = {0}""" # Only the end of the data transfer is inside the time window - queryBegin = """ SELECT sum(? - DataStrobeBegin) FROM transactions Where DataStrobeBegin >= ? and DataStrobeBegin < ? and DataStrobeEnd > ? and TThread = {0}""" # Only the beginning of the data transfer is inside the time window - queryPart = """ SELECT DataStrobeBegin FROM transactions Where DataStrobeBegin <= ? and DataStrobeEnd >= ? and TThread = {0}""" # The data transfer occupies all the time window + ## All possible cases of data transfers inside a time window: + + # The data transfer begins and ends inside the time window + queryFull = """ + SELECT + SUM(DataStrobeEnd - DataStrobeBegin) + FROM + transactions + WHERE + DataStrobeBegin >= ? + AND DataStrobeEnd <= ? + AND TThread = {0} + """ + + # Only the end of the data transfer is inside the time window + queryEnd = """ + SELECT + SUM(DataStrobeEnd - ? ) + FROM + transactions + WHERE + DataStrobeBegin < ? + AND DataStrobeEnd > ? + AND DataStrobeEnd <=? + AND TThread = {0} + """ + + # Only the beginning of the data transfer is inside the time window + queryBegin = """ + SELECT + SUM( ? - DataStrobeBegin) + FROM + transactions + WHERE + DataStrobeBegin >= ? + AND DataStrobeBegin < ? + AND DataStrobeEnd > ? + AND TThread = {0} + """ + + # The data transfer occupies all the time window + queryPart = """ + SELECT + DataStrobeBegin + FROM + transactions + WHERE + DataStrobeBegin <= ? + AND DataStrobeEnd >= ? + AND TThread = {0} + """ queryFull = queryFull.format(thread_ID) queryEnd = queryEnd.format(thread_ID) @@ -95,13 +148,7 @@ def memory_utilisation_window_thread(connection, tracePath, steps, thread_ID): outputFileNameBWMatlab, basename = createOutputFilename(tracePath, 'memory_utilization_percent', 'thread_' + str(thread_ID) + '_', 'txt') return bandwidthPercentage, bandwidth, outputFileNameBWMatlab - -def plot(function): - plots.append(function) - return function - - -#@plot +@plot def memory_utilisation_window(connection, tracePath, steps): # This function determines the average memory bandwidth over time in # percentage and in Gbit/s. The average bandwidth over time is done @@ -118,11 +165,53 @@ def memory_utilisation_window(connection, tracePath, steps): windowSize = getWindowSize(connection) maxDataRate = maximum_data_rate(connection) - # 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 + ## All possible cases of data transfers inside a time window: + + # The data transfer begins and ends inside the time window + queryFull = """ + SELECT + SUM(DataStrobeEnd - DataStrobeBegin) + FROM + transactions + WHERE + DataStrobeBegin >= ? + AND DataStrobeEnd <= ? + """ + + # Only the end of the data transfer is inside the time window + queryEnd = """ + SELECT + SUM(DataStrobeEnd - ?) + FROM + transactions + WHERE + DataStrobeBegin < ? + AND DataStrobeEnd > ? + AND DataStrobeEnd <= ? + """ + + # Only the beginning of the data transfer is inside the time window + queryBegin = """ + SELECT + SUM(? - DataStrobeBegin) + FROM + transactions + WHERE + DataStrobeBegin >= ? + AND DataStrobeBegin < ? + AND DataStrobeEnd > ? + """ + + # The data transfer occupies all the time window + queryPart = """ + SELECT + DataStrobeBegin + FROM + transactions + WHERE + DataStrobeBegin <= ? + AND DataStrobeEnd >= ? + """ bandwidthPercentage, bandwidth, maximumPercentage = calculate_bandwidth_util(connection, windowSize, steps, queryFull, queryEnd, queryBegin, queryPart) @@ -131,10 +220,6 @@ def memory_utilisation_window(connection, tracePath, steps): outputFileNameBWMatlab, basename = createOutputFilename(tracePath, 'memory_utilization_percent', '', 'txt') outputFiles = "{0}\n\t{1}\n\t{2}\n\t".format(outputFileNameGBPS, outputFileNamePercent, outputFileNameBWMatlab) - import matplotlib.pyplot as plt - import numpy as np - from matplotlib.backends.backend_pdf import PdfPages - # windowSize/1000: picoseconds to nanoseconds conversion time = np.arange(0, (steps+1)*windowSize/1000, windowSize/1000) maxBandwidth = [maxDataRate/1024] * (steps+1) @@ -196,12 +281,238 @@ def memory_utilisation_window(connection, tracePath, steps): return outputFiles +@plot +def response_latency_window(connection, tracePath, steps): + windowSize = getWindowSize(connection) + + cursor = connection.cursor() + query = """ + SELECT + avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ? + """ + outputFileName, basename = createOutputFilename(tracePath, 'response_latency', '', 'pdf') + outputFile = "{0}\n\t".format(outputFileName) + + LatencyFigure = plt.figure(figsize=(10, 5), dpi=300) + LatencyFigurePlot = LatencyFigure.add_subplot(111) + LatencyFigurePlot.set_xlabel('Time [ns]') + LatencyFigurePlot.set_ylabel('Response Latency [ns]') + LatencyFigurePlot.set_title('Average Response Latency: ' + str(basename)) + LatencyFigurePlot.grid(True) + + time = [None] * steps + latency = [None] * steps + + for i in range(steps): + cursor.execute(query, (i * windowSize, (i + 1) * windowSize)) + result = cursor.fetchone()[0] + time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns + latency[i] = result + + LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency") + LatencyFigurePlot.legend(loc="upper left") + + pdf = PdfPages(outputFileName) + pdf.savefig(LatencyFigure) + pdf.close() + LatencyFigurePlot.clear() + plt.close() + + return outputFile + +@plot +def wr_response_latency_window(connection, tracePath, steps): + windowSize = getWindowSize(connection) + + cursor = connection.cursor() + query = """ + SELECT + avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ? + AND Transactions.Command = "W" + """ + outputFileName, basename = createOutputFilename(tracePath, 'wr_response_latency', '', 'pdf') + outputFile = "{0}\n\t".format(outputFileName) + + LatencyFigure = plt.figure(figsize=(10, 5), dpi=300) + LatencyFigurePlot = LatencyFigure.add_subplot(111) + LatencyFigurePlot.set_xlabel('Time [ns]') + LatencyFigurePlot.set_ylabel('Response Latency [ns]') + LatencyFigurePlot.set_title('Average Write Response Latency: ' + str(basename)) + LatencyFigurePlot.grid(True) + + time = [None] * steps + latency = [None] * steps + + for i in range(steps): + cursor.execute(query, (i * windowSize, (i + 1) * windowSize)) + result = cursor.fetchone()[0] + time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns + latency[i] = result + + LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency") + LatencyFigurePlot.legend(loc="upper left") + + pdf = PdfPages(outputFileName) + pdf.savefig(LatencyFigure) + pdf.close() + LatencyFigurePlot.clear() + plt.close() + + return outputFile + +@plot +def rd_response_latency_window(connection, tracePath, steps): + windowSize = getWindowSize(connection) + + cursor = connection.cursor() + query = """ + SELECT + avg(RESP.PHASEBEGIN - REQ.PHASEBEGIN) / 1000 + FROM + PHASES REQ, + PHASES RESP + INNER JOIN + Transactions + ON REQ.TRANSACT = Transactions.ID + WHERE + REQ.PHASENAME = 'REQ' + AND RESP.PHASENAME = 'RESP' + AND REQ.TRANSACT = RESP.TRANSACT + AND RESP.PHASEBEGIN >= ? and RESP.PHASEEND <= ? + AND Transactions.Command = "R" + """ + outputFileName, basename = createOutputFilename(tracePath, 'rd_response_latency', '', 'pdf') + outputFile = "{0}\n\t".format(outputFileName) + + LatencyFigure = plt.figure(figsize=(10, 5), dpi=300) + LatencyFigurePlot = LatencyFigure.add_subplot(111) + LatencyFigurePlot.set_xlabel('Time [ns]') + LatencyFigurePlot.set_ylabel('Response Latency [ns]') + LatencyFigurePlot.set_title('Average Read Response Latency: ' + str(basename)) + LatencyFigurePlot.grid(True) + + time = [None] * steps + latency = [None] * steps + + for i in range(steps): + cursor.execute(query, (i * windowSize, (i + 1) * windowSize)) + result = cursor.fetchone()[0] + time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns + latency[i] = result + + LatencyFigurePlot.plot(time, latency, linewidth=0.5, label="Latency") + LatencyFigurePlot.legend(loc="upper left") + + pdf = PdfPages(outputFileName) + pdf.savefig(LatencyFigure) + pdf.close() + LatencyFigurePlot.clear() + plt.close() + + return outputFile + +@plot +def command_bus_utilisation_window(connection, tracePath, steps): + windowSize = getWindowSize(connection) + + cursor = connection.cursor() + + # Query that sums all lengths that are completely contained in the window + query_full = """ + SELECT + SUM(CommandLengths.Length) + FROM + Phases, + GeneralInfo + INNER JOIN + CommandLengths + ON Phases.PhaseName = CommandLengths.Command + WHERE + Phases.PhaseBegin >= ? + AND (Phases.PhaseBegin + (CommandLengths.Length * GeneralInfo.clk)) < ? + """ + + # Gets the PhaseBegin of the command that reaches out of the window + # query_border = """ + # SELECT + # Phases.PhaseBegin + # FROM + # Phases, + # GeneralInfo + # INNER JOIN + # CommandLengths + # ON Phases.PhaseName = CommandLengths.Command + # WHERE + # Phases.PhaseBegin >= ? + # AND Phases.PhaseBegin < ? + # AND (Phases.PhaseBegin + (CommandLengths.Length * GeneralInfo.clk)) >= ? + # """ + + outputFileName, basename = createOutputFilename(tracePath, 'command_bus_utilisation', '', 'pdf') + outputFile = "{0}\n\t".format(outputFileName) + + LatencyFigure = plt.figure(figsize=(10, 5), dpi=300) + LatencyFigurePlot = LatencyFigure.add_subplot(111) + LatencyFigurePlot.set_xlabel('Time [ns]') + LatencyFigurePlot.set_ylabel('Utilization [%]') + LatencyFigurePlot.set_title('Command Bus Utilization: ' + str(basename)) + LatencyFigurePlot.grid(True) + + clk, _ = getClock(connection) + + time = [None] * steps + utilization = [None] * steps + + for i in range(steps): + left_limit = i * windowSize + right_limit = (i + 1) * windowSize + + cursor.execute(query_full, (left_limit, right_limit)) + result = cursor.fetchone()[0] + + if (result is None): + result = 0 + + cmdBusOccupied = result * clk + + time[i] = ((i * windowSize) - (windowSize / 2)) / 1000 # ps to ns + utilization[i] = cmdBusOccupied / windowSize * 100 + + if (utilization[i] > 100): + print(left_limit, right_limit) + + LatencyFigurePlot.plot(time, utilization, linewidth=0.5, label="Utilization") + LatencyFigurePlot.legend(loc="upper left") + + pdf = PdfPages(outputFileName) + pdf.savefig(LatencyFigure) + pdf.close() + LatencyFigurePlot.clear() + plt.close() + + return outputFile + @plot def queue_window(connection, tracePath, steps): - - import matplotlib.pyplot as plt - from matplotlib.backends.backend_pdf import PdfPages - cursor = connection.cursor() cursor.execute("select max(BufferNumber) from BufferDepth;") bufferNumber = int(cursor.fetchone()[0]) + 1 @@ -256,7 +567,6 @@ def power_window(connection, tracePath, steps): cursor.execute(" SELECT * FROM Power") - import numpy as np window = float(windowSize) / pow(10, 12) time = np.arange(0, (windowSize * (steps + 1)) / pow(10, 6), windowSize / pow(10, 6)) power = np.full(len(time), 0) @@ -282,9 +592,6 @@ def power_window(connection, tracePath, steps): outputFileName, basename = createOutputFilename(tracePath, 'power', '', 'pdf') outputFile = "{0}\n\t".format(outputFileName) - import matplotlib.pyplot as plt - from matplotlib.backends.backend_pdf import PdfPages - PowFigure = plt.figure(figsize=(10, 5), dpi=300) PowFigurePlot = PowFigure.add_subplot(111) PowFigurePlot.set_xlabel('Time [us]') @@ -301,104 +608,6 @@ def power_window(connection, tracePath, steps): return outputFile -def latency_analysis(connection, tracePath, steps): - from collections import Counter - query = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000), t.id - FROM Transactions t, Phases p1, Phases p2 - WHERE t.id = p1.Transact - AND t.id = p2.Transact - AND p1.PhaseName = "REQ" - AND p2.PhaseName = "RESP" """ - cursor = connection.cursor() - cursor.execute(query) - results = [] - while True: - result = cursor.fetchone() - if (result is not None): - results.append([result[0], result[1]]) - else: - break - - # Create histogram for analysis: - hist = {} - transactions = {} - for i in results: - hist[i[0]] = hist.get(i[0], 0) + 1 - if i[0] in transactions: - transactions[i[0]].append(i[1]) - else: - transactions[i[0]] = [] - - # Find N highest bins - N = 3 - k = Counter(hist) - high = k.most_common(3) - - for i in high: - print(i[0]," :",i[1]," ") - print(transactions[i[0]]) - - return "none\n" - -#@plot -def latency_histogram(connection, tracePath, steps): - # This function plots an histogram with access latencys - - def plot_latency_histogram(dataArray, outputFileName, basename): - # plot into PDF file - import matplotlib - matplotlib.use('TkAgg') - import matplotlib.pyplot as plt - from matplotlib.backends.backend_pdf import PdfPages - - plt.hist(dataArray, bins=numberOfBins, range=latencyRange, histtype='bar', facecolor='green') - plt.grid(True) - plt.xlabel("Access Time [ns]") - plt.ylabel("Number of Accesses (Frequency)") - plt.title("Latency Histogram " + str(basename)) - pdf = PdfPages(outputFileName) - pdf.savefig() - pdf.close() - plt.close() - - def create_latency_hist(connection, tracePath, target_measurement, query): - # form output file name - ofbname = 'access_latency_hist' - outputFileName, basename = createOutputFilename(tracePath, ofbname, target_measurement, 'pdf') - # return log string - outputFile = "{0}\n\t".format(outputFileName) - # access database - resultArray = accessDatabase(connection, query) - # plot - plot_latency_histogram(resultArray, outputFileName, basename) - return outputFile - - # create overal latency histogram - query = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000) - FROM Transactions t, Phases p1, Phases p2 - WHERE t.id = p1.Transact - AND t.id = p2.Transact - AND p1.PhaseName = "REQ" - AND p2.PhaseName = "RESP" """ - outputFile = create_latency_hist(connection, tracePath, '', query) - - # create per-thread latency histogram - threads = getThreads(connection) - if (len(threads) > 1): - queryThread = """ SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000) - FROM Transactions t, Phases p1, Phases p2 - WHERE t.id = p1.Transact - AND t.id = p2.Transact - AND p1.PhaseName = "REQ" - AND p2.PhaseName = "RESP" - AND t.TThread = {0} """ - for thread in threads: - thrname = 'thread_' + str(thread) + '_' - outputFile += create_latency_hist(connection, tracePath, thrname, queryThread.format(thread)) - - return outputFile - - def generatePlots(pathToTrace): connection = sqlite3.connect(pathToTrace)