Added extension mechanism and ported DDR5, LPDDR5, HBM3, TraceAnalyzer
This commit is contained in:
717
extensions/apps/traceAnalyzer/data/tracedb.cpp
Normal file
717
extensions/apps/traceAnalyzer/data/tracedb.cpp
Normal file
@@ -0,0 +1,717 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Technische Universität 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:
|
||||
* Janik Schlemminger
|
||||
* Robert Gernhardt
|
||||
* Matthias Jung
|
||||
* Derek Christ
|
||||
* Iron Prando da Silva
|
||||
*/
|
||||
|
||||
#include <QString>
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QSqlError>
|
||||
#include <iostream>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
#include "data/tracedb.h"
|
||||
#include "businessObjects/phases/phasefactory.h"
|
||||
|
||||
|
||||
//define symbol printqueries if all queries should be printed to the console
|
||||
//#define printqueries
|
||||
|
||||
TraceDB::TraceDB(const QString& path, bool openExisting)
|
||||
{
|
||||
this->pathToDB = path;
|
||||
|
||||
database = QSqlDatabase::database(path);
|
||||
if (database.isValid() && database.isOpen())
|
||||
{
|
||||
// Close the database connection if it exists and was not closed yet.
|
||||
database.close();
|
||||
QSqlDatabase::removeDatabase(path);
|
||||
}
|
||||
|
||||
database = QSqlDatabase::addDatabase("QSQLITE", path);
|
||||
database.setDatabaseName(path);
|
||||
if (!database.open())
|
||||
{
|
||||
qDebug() << database.lastError().text();
|
||||
}
|
||||
if (!openExisting)
|
||||
dropAndCreateTables();
|
||||
prepareQueries();
|
||||
generalInfo = getGeneralInfoFromDB();
|
||||
commandLengths = getCommandLengthsFromDB();
|
||||
}
|
||||
|
||||
void TraceDB::prepareQueries()
|
||||
{
|
||||
selectTransactionsByTimespan = QSqlQuery(database);
|
||||
if (!selectTransactionsByTimespan.prepare(queryTexts.selectTransactionsByTimespan))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
selectTransactionById = QSqlQuery(database);
|
||||
if (!selectTransactionById.prepare(queryTexts.selectTransactionById))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
selectDebugMessagesByTimespan = QSqlQuery(database);
|
||||
if (!selectDebugMessagesByTimespan.prepare("SELECT time, Message FROM DebugMessages WHERE :begin <= time AND time <= :end "))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
selectDebugMessagesByTimespanWithLimit = QSqlQuery(database);
|
||||
if (!selectDebugMessagesByTimespanWithLimit.prepare("SELECT time, Message FROM DebugMessages WHERE :begin <= time AND time <= :end LIMIT :limit"))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
checkDependenciesExist = QSqlQuery(database);
|
||||
if (!checkDependenciesExist.prepare(queryTexts.checkDependenciesExist))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
selectDependenciesByTimespan = QSqlQuery(database);
|
||||
if (!selectDependenciesByTimespan.prepare(queryTexts.selectDependenciesByTimespan))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
}
|
||||
|
||||
void TraceDB::updateComments(const std::vector<CommentModel::Comment> &comments)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("DELETE FROM Comments");
|
||||
executeQuery(query);
|
||||
query.prepare("insert into Comments values(:time,:text)");
|
||||
|
||||
for (const auto &comment : comments)
|
||||
{
|
||||
query.bindValue(":time", comment.time);
|
||||
query.bindValue(":text", comment.text);
|
||||
executeQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
void TraceDB::updateFileDescription(const QString &description)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("UPDATE GeneralInfo SET Description=:description");
|
||||
query.bindValue(":description", description);
|
||||
executeQuery(query);
|
||||
}
|
||||
|
||||
void TraceDB::refreshData()
|
||||
{
|
||||
prepareQueries();
|
||||
generalInfo = getGeneralInfoFromDB();
|
||||
}
|
||||
|
||||
//QueryText must select the fields
|
||||
//TransactionID, Ranges.begin, Ranges.end, Address, TThread, TChannel, TBank, TRow, TColumn, Phases.ID AS PhaseID, PhaseName, PhaseBegin, PhaseEnd
|
||||
std::vector<std::shared_ptr<Transaction>> TraceDB::getTransactionsWithCustomQuery(const QString& queryText)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare(queryText);
|
||||
executeQuery(query);
|
||||
return parseTransactionsFromQuery(query);
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Transaction>> TraceDB::getTransactionsInTimespan(const Timespan &span, bool updateVisiblePhases)
|
||||
{
|
||||
selectTransactionsByTimespan.bindValue(":begin", span.Begin());
|
||||
selectTransactionsByTimespan.bindValue(":end", span.End());
|
||||
executeQuery(selectTransactionsByTimespan);
|
||||
return parseTransactionsFromQuery(selectTransactionsByTimespan, updateVisiblePhases);
|
||||
}
|
||||
|
||||
bool TraceDB::checkDependencyTableExists()
|
||||
{
|
||||
executeQuery(checkDependenciesExist);
|
||||
|
||||
bool exists = checkDependenciesExist.next() && checkDependenciesExist.value(0).toInt() == 1;
|
||||
|
||||
checkDependenciesExist.finish();
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
void TraceDB::updateDependenciesInTimespan(const Timespan &span)
|
||||
{
|
||||
if (checkDependencyTableExists())
|
||||
{
|
||||
selectDependenciesByTimespan.bindValue(":begin", span.Begin());
|
||||
selectDependenciesByTimespan.bindValue(":end", span.End());
|
||||
executeQuery(selectDependenciesByTimespan);
|
||||
mUpdateDependenciesFromQuery(selectDependenciesByTimespan);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Remove exception
|
||||
std::shared_ptr<Transaction> TraceDB::getTransactionByID(ID id)
|
||||
{
|
||||
selectTransactionById.bindValue(":id", id);
|
||||
executeQuery(selectTransactionById);
|
||||
auto result = parseTransactionsFromQuery(selectTransactionById);
|
||||
if (!result.empty())
|
||||
return result[0];
|
||||
else
|
||||
throw sqlException(("Transaction with ID " + QString::number(
|
||||
id) + " not in DB").toStdString(), this->pathToDB.toStdString());
|
||||
}
|
||||
|
||||
|
||||
std::shared_ptr<Transaction> TraceDB::getNextActivate(traceTime time)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead +
|
||||
"WHERE PhaseBegin > :traceTime AND PhaseName = 'ACT' ORDER BY PhaseBegin ASC LIMIT 1";
|
||||
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":traceTime", time);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
std::shared_ptr<Transaction> TraceDB::getNextPrecharge(traceTime time)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead +
|
||||
"WHERE PhaseBegin > :traceTime AND PhaseName "
|
||||
"IN ('PRE','PREPB','PREA','PREAB','PRESB') ORDER BY PhaseBegin ASC LIMIT 1";
|
||||
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":traceTime", time);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
// shared_ptr<Transaction> TraceDB::getNextActb(ID currentTransactionId)
|
||||
// {
|
||||
// QSqlQuery query(database);
|
||||
// QString queryText = queryTexts.queryHead +
|
||||
// "WHERE TransactionID > :currentID AND PhaseName = 'ACTB' LIMIT 1";
|
||||
//
|
||||
// query.prepare(queryText);
|
||||
// query.bindValue(":currentID", currentTransactionId);
|
||||
// executeQuery(query);
|
||||
// return parseTransactionFromQuery(query);
|
||||
// }
|
||||
|
||||
// shared_ptr<Transaction> TraceDB::getNextPreb(ID currentTransactionId)
|
||||
// {
|
||||
// QSqlQuery query(database);
|
||||
// QString queryText = queryTexts.queryHead +
|
||||
// "WHERE TransactionID > :currentID AND PhaseName = 'PREB' LIMIT 1";
|
||||
//
|
||||
// query.prepare(queryText);
|
||||
// query.bindValue(":currentID", currentTransactionId);
|
||||
// executeQuery(query);
|
||||
// return parseTransactionFromQuery(query);
|
||||
// }
|
||||
|
||||
std::shared_ptr<Transaction> TraceDB::getNextRefresh(traceTime time)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead +
|
||||
"WHERE PhaseBegin > :traceTime AND PhaseName "
|
||||
"IN ('REFAB','REFA','REFB','REFPB','REFP2B','REFSB','SREF','SREFB') ORDER BY PhaseBegin ASC LIMIT 1";
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":traceTime", time);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
std::shared_ptr<Transaction> TraceDB::getNextCommand(traceTime time)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead +
|
||||
"WHERE PhaseBegin > :traceTime ORDER BY PhaseBegin ASC LIMIT 1";
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":traceTime", time);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
// shared_ptr<Transaction> TraceDB::getNextRefb(ID currentTransactionId)
|
||||
// {
|
||||
// QSqlQuery query(database);
|
||||
// QString queryText = queryTexts.queryHead +
|
||||
// "WHERE TransactionID > :currentID AND PhaseName = 'REFB' LIMIT 1";
|
||||
//
|
||||
// query.prepare(queryText);
|
||||
// query.bindValue(":currentID", currentTransactionId);
|
||||
// executeQuery(query);
|
||||
// return parseTransactionFromQuery(query);
|
||||
// }
|
||||
|
||||
ID TraceDB::getTransactionIDFromPhaseID(ID phaseID)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT Transact FROM Phases WHERE ID=:id");
|
||||
query.bindValue(":id", phaseID);
|
||||
executeQuery(query);
|
||||
|
||||
if (query.next()) {
|
||||
return query.value(0).toInt();
|
||||
} else {
|
||||
throw sqlException("Phase with ID " + std::to_string(phaseID) + " not in db",
|
||||
this->pathToDB.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
GeneralInfo TraceDB::getGeneralInfoFromDB()
|
||||
{
|
||||
QVariant parameter;
|
||||
parameter = getParameterFromTable("NumberOfTransactions", "GeneralInfo");
|
||||
uint64_t numberOfTransactions = parameter.isValid() ? parameter.toULongLong() : 0;
|
||||
parameter = getParameterFromTable("TraceEnd", "GeneralInfo");
|
||||
traceTime traceEnd = parameter.isValid() ? static_cast<traceTime>(parameter.toULongLong()) : 0;
|
||||
parameter = getParameterFromTable("NumberOfRanks", "GeneralInfo");
|
||||
unsigned numberOfRanks = parameter.isValid() ? parameter.toUInt() : 1;
|
||||
parameter = getParameterFromTable("NumberOfBankgroups", "GeneralInfo");
|
||||
unsigned numberOfBankGroups = parameter.isValid() ? parameter.toUInt() : numberOfRanks;
|
||||
parameter = getParameterFromTable("NumberOfBanks", "GeneralInfo");
|
||||
unsigned numberOfBanks = parameter.isValid() ? parameter.toUInt() : numberOfBankGroups;
|
||||
parameter = getParameterFromTable("Clk", "GeneralInfo");
|
||||
uint64_t clkPeriod = parameter.isValid() ? parameter.toULongLong() : 1000;
|
||||
parameter = getParameterFromTable("UnitOfTime", "GeneralInfo");
|
||||
QString unitOfTime = parameter.isValid() ? parameter.toString() : "PS";
|
||||
parameter = getParameterFromTable("Traces", "GeneralInfo");
|
||||
QString traces = parameter.isValid() ? "Traces: " + parameter.toString() : "Traces: empty";
|
||||
parameter = getParameterFromTable("Memspec", "GeneralInfo");
|
||||
QString memspec = parameter.isValid() ? "Memspec: " + parameter.toString() : "Memspec: empty";
|
||||
parameter = getParameterFromTable("MCconfig", "GeneralInfo");
|
||||
QString mcconfig = parameter.isValid() ? "MCconfig: " + parameter.toString() : "MCconfig: empty";
|
||||
parameter = getParameterFromTable("WindowSize", "GeneralInfo");
|
||||
uint64_t windowSize = parameter.isValid() ? parameter.toULongLong() : 0;
|
||||
parameter = getParameterFromTable("RefreshMaxPostponed", "GeneralInfo");
|
||||
unsigned refreshMaxPostponed = parameter.isValid() ? parameter.toUInt() : 0;
|
||||
parameter = getParameterFromTable("RefreshMaxPulledin", "GeneralInfo");
|
||||
unsigned refreshMaxPulledin = parameter.isValid() ? parameter.toUInt() : 0;
|
||||
parameter = getParameterFromTable("ControllerThread", "GeneralInfo");
|
||||
unsigned controllerThread = parameter.isValid() ? parameter.toUInt() : UINT_MAX;
|
||||
parameter = getParameterFromTable("MaxBufferDepth", "GeneralInfo");
|
||||
unsigned maxBufferDepth = parameter.isValid() ? parameter.toUInt() : 8;
|
||||
parameter = getParameterFromTable("Per2BankOffset", "GeneralInfo");
|
||||
unsigned per2BankOffset = parameter.isValid() ? parameter.toUInt() : 1;
|
||||
parameter = getParameterFromTable("RowColumnCommandBus", "GeneralInfo");
|
||||
bool rowColumnCommandBus = parameter.isValid() && parameter.toBool();
|
||||
parameter = getParameterFromTable("PseudoChannelMode", "GeneralInfo");
|
||||
bool pseudoChannelMode = parameter.isValid() && parameter.toBool();
|
||||
|
||||
uint64_t numberOfPhases = getNumberOfPhases();
|
||||
|
||||
QString description = (traces + "\n");
|
||||
description += mcconfig + "\n";
|
||||
description += memspec + "\n";
|
||||
description += "Number of Transactions: " + QString::number(numberOfTransactions) + "\n";
|
||||
description += "Clock period: " + QString::number(clkPeriod) + " " + unitOfTime + "\n";
|
||||
description += "Length of trace: " + prettyFormatTime(traceEnd) + "\n";
|
||||
description += "Window size: " + QString::number(windowSize) + "\n";
|
||||
|
||||
return {numberOfTransactions, numberOfPhases, Timespan(0, traceEnd),
|
||||
numberOfRanks, numberOfBankGroups, numberOfBanks,
|
||||
description, unitOfTime, clkPeriod,
|
||||
windowSize, refreshMaxPostponed, refreshMaxPulledin,
|
||||
controllerThread, maxBufferDepth, per2BankOffset,
|
||||
rowColumnCommandBus, pseudoChannelMode};
|
||||
}
|
||||
|
||||
CommandLengths TraceDB::getCommandLengthsFromDB()
|
||||
{
|
||||
const std::string table = "CommandLengths";
|
||||
|
||||
auto getLengthFromDb = [=, &table](const std::string &command) -> QVariant
|
||||
{
|
||||
QSqlQuery query(("SELECT Length FROM " + table + " WHERE Command = \"" + command + "\"").c_str(), database);
|
||||
|
||||
if (query.first())
|
||||
return query.value(0);
|
||||
else
|
||||
return {};
|
||||
};
|
||||
|
||||
auto getCommandLength = [=, &table](const std::string &command) -> double
|
||||
{
|
||||
QVariant length = getLengthFromDb(command);
|
||||
|
||||
if (length.isValid())
|
||||
return length.toDouble();
|
||||
else
|
||||
{
|
||||
qDebug() << "CommandLength for" << command.c_str() << "not present in table" << table.c_str()
|
||||
<< ". Defaulting to 1.";
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
double NOP = getCommandLength("NOP");
|
||||
double RD = getCommandLength("RD");
|
||||
double WR = getCommandLength("RD");
|
||||
double RDA = getCommandLength("RDA");
|
||||
double WRA = getCommandLength("WRA");
|
||||
double ACT = getCommandLength("ACT");
|
||||
|
||||
double PREPB = getCommandLength("PREPB");
|
||||
double REFPB = getCommandLength("REFPB");
|
||||
|
||||
double RFMPB = getCommandLength("RFMPB");
|
||||
double REFP2B = getCommandLength("REFP2B");
|
||||
double RFMP2B = getCommandLength("RFMP2B");
|
||||
double PRESB = getCommandLength("PRESB");
|
||||
double REFSB = getCommandLength("REFSB");
|
||||
double RFMSB = getCommandLength("RFMSB");
|
||||
|
||||
double PREAB = getCommandLength("PREAB");
|
||||
double REFAB = getCommandLength("REFAB");
|
||||
|
||||
double RFMAB = getCommandLength("RFMAB");
|
||||
double PDEA = getCommandLength("PDEA");
|
||||
double PDXA = getCommandLength("PDXA");
|
||||
double PDEP = getCommandLength("PDEP");
|
||||
double PDXP = getCommandLength("PDXP");
|
||||
double SREFEN = getCommandLength("SREFEN");
|
||||
double 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};
|
||||
}
|
||||
|
||||
QVariant TraceDB::getParameterFromTable(const std::string& parameter, const std::string& table)
|
||||
{
|
||||
QSqlQuery query(("SELECT " + parameter + " FROM " + table).c_str(), database);
|
||||
if (query.first())
|
||||
return query.value(0);
|
||||
else
|
||||
{
|
||||
qDebug() << "Parameter " << parameter.c_str() << " not present in table " << table.c_str();
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t TraceDB::getNumberOfPhases()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT COUNT(ID) FROM Phases");
|
||||
executeQuery(query);
|
||||
|
||||
query.next();
|
||||
return query.value(0).toULongLong();
|
||||
}
|
||||
|
||||
std::vector<CommentModel::Comment> TraceDB::getComments()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT Time,Text From Comments");
|
||||
executeQuery(query);
|
||||
return parseCommentsFromQuery(query);
|
||||
}
|
||||
|
||||
|
||||
std::vector<CommentModel::Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span)
|
||||
{
|
||||
selectDebugMessagesByTimespan.bindValue(":begin", span.Begin());
|
||||
selectDebugMessagesByTimespan.bindValue(":end", span.End());
|
||||
executeQuery(selectDebugMessagesByTimespan);
|
||||
|
||||
return parseCommentsFromQuery(selectDebugMessagesByTimespan);
|
||||
}
|
||||
|
||||
std::vector<CommentModel::Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span,
|
||||
unsigned int limit = 50)
|
||||
{
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":begin", span.Begin());
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":end", span.End());
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":limit", limit);
|
||||
executeQuery(selectDebugMessagesByTimespanWithLimit);
|
||||
return parseCommentsFromQuery(selectDebugMessagesByTimespanWithLimit);
|
||||
}
|
||||
|
||||
DependencyInfos TraceDB::getDependencyInfos(DependencyInfos::Type infoType)
|
||||
{
|
||||
DependencyInfos dummy;
|
||||
if (!checkDependencyTableExists())
|
||||
{
|
||||
return dummy;
|
||||
}
|
||||
|
||||
switch (infoType)
|
||||
{
|
||||
case DependencyInfos::Type::DependencyType:
|
||||
{
|
||||
selectDependencyTypePercentages = QSqlQuery(database);
|
||||
if (!selectDependencyTypePercentages.prepare(queryTexts.selectDependencyTypePercentages))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
executeQuery(selectDependencyTypePercentages);
|
||||
return parseDependencyInfos(selectDependencyTypePercentages, infoType);
|
||||
}
|
||||
|
||||
case DependencyInfos::Type::TimeDependency:
|
||||
{
|
||||
selectTimeDependencyPercentages = QSqlQuery(database);
|
||||
if (!selectTimeDependencyPercentages.prepare(queryTexts.selectTimeDependencyPercentages))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
executeQuery(selectTimeDependencyPercentages);
|
||||
return parseDependencyInfos(selectTimeDependencyPercentages, infoType);
|
||||
}
|
||||
|
||||
case DependencyInfos::Type::DelayedPhase:
|
||||
{
|
||||
selectDelayedPhasePercentages = QSqlQuery(database);
|
||||
if (!selectDelayedPhasePercentages.prepare(queryTexts.selectDelayedPhasePercentages))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
executeQuery(selectDelayedPhasePercentages);
|
||||
return parseDependencyInfos(selectDelayedPhasePercentages, infoType);
|
||||
}
|
||||
|
||||
case DependencyInfos::Type::DependencyPhase:
|
||||
{
|
||||
selectDependencyPhasePercentages = QSqlQuery(database);
|
||||
if (!selectDependencyPhasePercentages.prepare(queryTexts.selectDependencyPhasePercentages))
|
||||
qDebug() << database.lastError().text();
|
||||
|
||||
executeQuery(selectDependencyPhasePercentages);
|
||||
return parseDependencyInfos(selectDependencyPhasePercentages, infoType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
QSqlDatabase TraceDB::getDatabase() const
|
||||
{
|
||||
return database;
|
||||
}
|
||||
|
||||
/* Helpers
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
std::shared_ptr<Transaction> TraceDB::parseTransactionFromQuery(QSqlQuery &query)
|
||||
{
|
||||
auto result = parseTransactionsFromQuery(query);
|
||||
if (!result.empty())
|
||||
return result[0];
|
||||
else
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Transaction>> TraceDB::parseTransactionsFromQuery(QSqlQuery &query, bool updateVisiblePhases)
|
||||
{
|
||||
if (updateVisiblePhases)
|
||||
{
|
||||
_visiblePhases.clear();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<Transaction>> result;
|
||||
|
||||
bool firstIteration = true;
|
||||
ID currentID = 0;
|
||||
int i = -1;
|
||||
|
||||
while (query.next())
|
||||
{
|
||||
ID id = query.value(0).toInt();
|
||||
|
||||
if (currentID != id || firstIteration)
|
||||
{
|
||||
++i;
|
||||
firstIteration = false;
|
||||
currentID = id;
|
||||
Timespan span(query.value(1).toLongLong(), query.value(2).toLongLong());
|
||||
uint64_t address = query.value(3).toULongLong();
|
||||
unsigned int dataLength = query.value(4).toUInt();
|
||||
unsigned int thread = query.value(5).toUInt();
|
||||
unsigned int channel = query.value(6).toUInt();
|
||||
QString command = query.value(7).toString();
|
||||
result.push_back(std::make_shared<Transaction>(id, std::move(command), address, dataLength, thread, channel,
|
||||
span, generalInfo.clkPeriod));
|
||||
}
|
||||
|
||||
unsigned int phaseID = query.value(8).toInt();
|
||||
QString phaseName = query.value(9).toString();
|
||||
Timespan span(query.value(10).toLongLong(), query.value(11).toLongLong());
|
||||
Timespan spanOnDataStrobe(query.value(12).toLongLong(), query.value(13).toLongLong());
|
||||
unsigned int rank = query.value(14).toUInt();
|
||||
unsigned int bankGroup = query.value(15).toUInt();
|
||||
unsigned int bank = query.value(16).toUInt();
|
||||
unsigned int row = query.value(17).toUInt();
|
||||
unsigned int column = query.value(18).toUInt();
|
||||
unsigned int burstLength = query.value(19).toUInt();
|
||||
auto phase = PhaseFactory::createPhase(phaseID, phaseName, span, spanOnDataStrobe, rank, bankGroup, bank,
|
||||
row, column, burstLength, result.at(result.size() - 1), *this);
|
||||
result.at(result.size() - 1)->addPhase(phase);
|
||||
|
||||
if (updateVisiblePhases)
|
||||
{
|
||||
_visiblePhases[phaseID] = phase;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TraceDB::mUpdateDependenciesFromQuery(QSqlQuery &query)
|
||||
{
|
||||
DependencyType type;
|
||||
while (query.next())
|
||||
{
|
||||
ID delayedID = query.value(0).toInt();
|
||||
ID dependencyID = query.value(4).toInt();
|
||||
|
||||
QString dependencyTypeStr = query.value(2).toString();
|
||||
if (dependencyTypeStr == "bank")
|
||||
{
|
||||
type = DependencyType::IntraBank;
|
||||
}
|
||||
else if (dependencyTypeStr == "rank")
|
||||
{
|
||||
type = DependencyType::IntraRank;
|
||||
}
|
||||
else if (dependencyTypeStr == "interRank")
|
||||
{
|
||||
type = DependencyType::InterRank;
|
||||
}
|
||||
|
||||
QString timeDependencyStr = query.value(3).toString();
|
||||
|
||||
if (_visiblePhases.count(delayedID) > 0)
|
||||
{
|
||||
|
||||
if (_visiblePhases.count(dependencyID) > 0)
|
||||
{
|
||||
|
||||
_visiblePhases[delayedID]->addDependency(std::make_shared<PhaseDependency>(
|
||||
PhaseDependency(type, timeDependencyStr, _visiblePhases[dependencyID])));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
_visiblePhases[delayedID]->addDependency(
|
||||
std::make_shared<PhaseDependency>(PhaseDependency(type, timeDependencyStr)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO delayed phase not visible?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<CommentModel::Comment> TraceDB::parseCommentsFromQuery(QSqlQuery &query)
|
||||
{
|
||||
std::vector<CommentModel::Comment> result;
|
||||
while (query.next())
|
||||
{
|
||||
result.push_back(CommentModel::Comment{query.value(0).toLongLong(),
|
||||
query.value(1).toString()});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
DependencyInfos TraceDB::parseDependencyInfos(QSqlQuery &query, const DependencyInfos::Type infoType)
|
||||
{
|
||||
DependencyInfos infos(infoType);
|
||||
|
||||
while (query.next())
|
||||
{
|
||||
infos.addInfo({query.value(0).toString(), query.value(1).toFloat()});
|
||||
}
|
||||
|
||||
query.finish();
|
||||
|
||||
return infos;
|
||||
}
|
||||
|
||||
void TraceDB::executeQuery(QSqlQuery query)
|
||||
{
|
||||
|
||||
//query.exec returns bool indicating if the query was sucessfull
|
||||
if (query.exec()) {
|
||||
#ifdef printqueries
|
||||
cout << queryToString(query).toStdString() << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
else {
|
||||
query.finish();
|
||||
throw sqlException( ("Query:\n " + queryToString(query) + "\n failed. Error: \n"
|
||||
+
|
||||
query.lastError().text()).toStdString(), this->pathToDB.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
QString TraceDB::queryToString(const QSqlQuery& query)
|
||||
{
|
||||
QString str = query.lastQuery();
|
||||
QMapIterator<QString, QVariant> it(query.boundValues());
|
||||
while (it.hasNext()) {
|
||||
it.next();
|
||||
str.replace(it.key(), it.value().toString());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void TraceDB::dropAndCreateTables()
|
||||
{
|
||||
executeScriptFile("common/static/createTraceDB.sql");
|
||||
}
|
||||
|
||||
void TraceDB::executeScriptFile(const QString& fileName)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QFile scriptFile(fileName);
|
||||
|
||||
if (scriptFile.open(QIODevice::ReadOnly)) {
|
||||
// The SQLite driver executes only a single (the first) query in the QSqlQuery
|
||||
// if the script contains more queries, it needs to be splitted.
|
||||
QStringList scriptQueries = QTextStream(&scriptFile).readAll().split(';');
|
||||
|
||||
for (QString &queryTxt : scriptQueries) {
|
||||
if (queryTxt.trimmed().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!query.exec(queryTxt)) {
|
||||
throw sqlException("Querry failed:" + query.lastError().text().toStdString(),
|
||||
this->pathToDB.toStdString());
|
||||
}
|
||||
query.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user