Added interface for dependency calculation.

This commit is contained in:
Iron Prando da Silva
2021-12-13 16:30:45 +01:00
parent 0e1245ad98
commit 7bfb128132
16 changed files with 343 additions and 239 deletions

View File

@@ -101,6 +101,7 @@ add_executable(TraceAnalyzer
presentation/traceselector.cpp
businessObjects/configmodels.cpp
businessObjects/commentmodel.cpp
businessObjects/dependencymodels.cpp
businessObjects/dramTimeDependencies/dramtimedependenciesIF.cpp
businessObjects/dramTimeDependencies/DDR3TimeDependencies.cpp

View File

@@ -283,142 +283,3 @@ QModelIndex MemSpecModel::parent(const QModelIndex &index) const
return createIndex(parentNode->getRow(), 0, const_cast<Node *>(parentNode));
}
DependencyInfosModel::DependencyInfosModel(TraceDB &traceFile, QObject *parent) : QAbstractItemModel(parent)
{
mDepInfosDepType = traceFile.getDependencyInfos(DependencyInfos::Type::DependencyType);
mDepInfosTimeDep = traceFile.getDependencyInfos(DependencyInfos::Type::TimeDependency);
mDepInfosDelPhase = traceFile.getDependencyInfos(DependencyInfos::Type::DelayedPhase);
mDepInfosDepPhase = traceFile.getDependencyInfos(DependencyInfos::Type::DependencyPhase);
if (traceFile.checkDependencyTableExists())
{
parseInfos();
}
}
int DependencyInfosModel::Node::getRow() const
{
if (!parent)
return 0;
const auto &siblings = parent->children;
const auto siblingsIt = std::find_if(siblings.begin(), siblings.end(),
[this](const std::unique_ptr<Node> &node) { return node.get() == this; });
Q_ASSERT(siblingsIt != siblings.end());
return std::distance(siblings.begin(), siblingsIt);
}
void DependencyInfosModel::parseInfos()
{
std::vector<std::pair<QString, DependencyInfos &>> infos = {{"Dependency Granularity", mDepInfosDepType},
{"Time Dependencies", mDepInfosTimeDep},
{"Delayed Phases", mDepInfosDelPhase},
{"Dependency Phases", mDepInfosDepPhase}};
for (auto pair : infos)
{
std::unique_ptr<Node> node = std::unique_ptr<Node>(new Node({pair.first, ""}, rootNode.get()));
for (auto v : pair.second.getInfos())
{
QString value = QString::number(v.value) + " %";
node->children.push_back(std::move(std::unique_ptr<Node>(new Node({v.id, value}, node.get()))));
}
rootNode->children.push_back(std::move(node));
}
}
int DependencyInfosModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
const Node *parentNode;
if (!parent.isValid())
parentNode = rootNode.get();
else
parentNode = static_cast<const Node *>(parent.internalPointer());
return parentNode->childCount();
}
int DependencyInfosModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 2;
}
QVariant DependencyInfosModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::ToolTipRole)
return QVariant();
auto *node = static_cast<const Node *>(index.internalPointer());
if (index.column() == 0)
return QVariant(node->data.first);
else
return QVariant(node->data.second);
}
QVariant DependencyInfosModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
{
switch (section)
{
case 0:
return "Field";
case 1:
return "Percentage";
default:
break;
}
}
return QVariant();
}
QModelIndex DependencyInfosModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
const Node *parentNode;
if (!parent.isValid())
parentNode = rootNode.get();
else
parentNode = static_cast<const Node *>(parent.internalPointer());
const Node *node = parentNode->children[row].get();
return createIndex(row, column, const_cast<Node *>(node));
}
QModelIndex DependencyInfosModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
const Node *childNode = static_cast<const Node *>(index.internalPointer());
const Node *parentNode = childNode->parent;
if (!parentNode)
return QModelIndex();
return createIndex(parentNode->getRow(), 0, const_cast<Node *>(parentNode));
}

View File

@@ -31,7 +31,6 @@
*
* Authors:
* Derek Christ
* Iron Prando da Silva
*/
#ifndef CONFIGMODELS_H
@@ -124,59 +123,4 @@ private:
std::unique_ptr<Node> rootNode = std::unique_ptr<Node>(new Node);
};
class DependencyInfosModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit DependencyInfosModel(TraceDB &traceFile, QObject *parent = nullptr);
~DependencyInfosModel()
{
}
protected:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &index) const override;
private:
DependencyInfos mDepInfosDepType;
DependencyInfos mDepInfosTimeDep;
DependencyInfos mDepInfosDelPhase;
DependencyInfos mDepInfosDepPhase;
void parseInfos();
struct Node
{
using NodeData = std::pair<QString, QString>;
Node()
{
}
Node(NodeData data, const Node *parent) : data(data), parent(parent)
{
}
/**
* Gets the row relative to its parent.
*/
int getRow() const;
int childCount() const
{
return children.size();
}
NodeData data;
const Node *parent = nullptr;
std::vector<std::unique_ptr<Node>> children;
};
std::unique_ptr<Node> rootNode = std::unique_ptr<Node>(new Node);
};
#endif // CONFIGMODELS_H

View File

@@ -0,0 +1,141 @@
#include "dependencymodels.h"
DependencyInfosModel::DependencyInfosModel(TraceDB &traceFile, QObject *parent) : QAbstractItemModel(parent)
{
mDepInfosDepType = traceFile.getDependencyInfos(DependencyInfos::Type::DependencyType);
mDepInfosTimeDep = traceFile.getDependencyInfos(DependencyInfos::Type::TimeDependency);
mDepInfosDelPhase = traceFile.getDependencyInfos(DependencyInfos::Type::DelayedPhase);
mDepInfosDepPhase = traceFile.getDependencyInfos(DependencyInfos::Type::DependencyPhase);
if (traceFile.checkDependencyTableExists())
{
parseInfos();
}
}
int DependencyInfosModel::Node::getRow() const
{
if (!parent)
return 0;
const auto &siblings = parent->children;
const auto siblingsIt = std::find_if(siblings.begin(), siblings.end(),
[this](const std::unique_ptr<Node> &node) { return node.get() == this; });
Q_ASSERT(siblingsIt != siblings.end());
return std::distance(siblings.begin(), siblingsIt);
}
void DependencyInfosModel::parseInfos()
{
std::vector<std::pair<QString, DependencyInfos &>> infos = {{"Dependency Granularity", mDepInfosDepType},
{"Time Dependencies", mDepInfosTimeDep},
{"Delayed Phases", mDepInfosDelPhase},
{"Dependency Phases", mDepInfosDepPhase}};
for (auto pair : infos)
{
std::unique_ptr<Node> node = std::unique_ptr<Node>(new Node({pair.first, ""}, rootNode.get()));
for (auto v : pair.second.getInfos())
{
QString value = QString::number(v.value) + " %";
node->children.push_back(std::move(std::unique_ptr<Node>(new Node({v.id, value}, node.get()))));
}
rootNode->children.push_back(std::move(node));
}
}
int DependencyInfosModel::rowCount(const QModelIndex &parent) const
{
if (parent.column() > 0)
return 0;
const Node *parentNode;
if (!parent.isValid())
parentNode = rootNode.get();
else
parentNode = static_cast<const Node *>(parent.internalPointer());
return parentNode->childCount();
}
int DependencyInfosModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return 2;
}
QVariant DependencyInfosModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid())
return QVariant();
if (role != Qt::DisplayRole && role != Qt::ToolTipRole)
return QVariant();
auto *node = static_cast<const Node *>(index.internalPointer());
if (index.column() == 0)
return QVariant(node->data.first);
else
return QVariant(node->data.second);
}
QVariant DependencyInfosModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal)
{
switch (section)
{
case 0:
return "Field";
case 1:
return "Percentage";
default:
break;
}
}
return QVariant();
}
QModelIndex DependencyInfosModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent))
return QModelIndex();
const Node *parentNode;
if (!parent.isValid())
parentNode = rootNode.get();
else
parentNode = static_cast<const Node *>(parent.internalPointer());
const Node *node = parentNode->children[row].get();
return createIndex(row, column, const_cast<Node *>(node));
}
QModelIndex DependencyInfosModel::parent(const QModelIndex &index) const
{
if (!index.isValid())
return QModelIndex();
const Node *childNode = static_cast<const Node *>(index.internalPointer());
const Node *parentNode = childNode->parent;
if (!parentNode)
return QModelIndex();
return createIndex(parentNode->getRow(), 0, const_cast<Node *>(parentNode));
}

View File

@@ -0,0 +1,65 @@
#pragma once
#include "../data/tracedb.h"
#include "phases/dependencyinfos.h"
#include <QAbstractTableModel>
#include <QListWidget>
#include <vector>
#include <utility>
class DependencyInfosModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit DependencyInfosModel(TraceDB &traceFile, QObject *parent = nullptr);
~DependencyInfosModel()
{
}
protected:
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
QModelIndex index(int row, int column, const QModelIndex &parent) const override;
QModelIndex parent(const QModelIndex &index) const override;
private:
DependencyInfos mDepInfosDepType;
DependencyInfos mDepInfosTimeDep;
DependencyInfos mDepInfosDelPhase;
DependencyInfos mDepInfosDepPhase;
void parseInfos();
struct Node
{
using NodeData = std::pair<QString, QString>;
Node()
{
}
Node(NodeData data, const Node *parent) : data(data), parent(parent)
{
}
/**
* Gets the row relative to its parent.
*/
int getRow() const;
int childCount() const
{
return children.size();
}
NodeData data;
const Node *parent = nullptr;
std::vector<std::unique_ptr<Node>> children;
};
std::unique_ptr<Node> rootNode = std::unique_ptr<Node>(new Node);
};

View File

@@ -50,6 +50,24 @@ void DDR3TimeDependencies::mInitializeValues() {
}
const std::vector<QString> DDR3TimeDependencies::getPossiblePhases() {
return {"ACT",
"RD",
"RDA",
"WR",
"WRA",
"PREPB",
"PREAB",
"REFAB",
"PDEA",
"PDXA",
"PDEP",
"PDXP",
"SREFEN",
"SREFEX"
};
}
DependencyMap DDR3TimeDependencies::mSpecializedGetDependencies() const {
DependencyMap dmap;

View File

@@ -7,6 +7,8 @@ class DDR3TimeDependencies : public DRAMTimeDependenciesIF {
public:
DDR3TimeDependencies(const QJsonObject& memspec, const uint clk);
static const std::vector<QString> getPossiblePhases();
protected:
void mInitializeValues() override;
DependencyMap mSpecializedGetDependencies() const override;

View File

@@ -16,3 +16,32 @@ std::shared_ptr<DRAMTimeDependenciesIF> DRAMTimeDependencyFactory::make(const Tr
}
}
const std::vector<QString> DRAMTimeDependencyFactory::possiblePhases(const TraceDB& tdb) {
uint clk; // Not used
const QJsonObject& memspec = DRAMTimeDependenciesIF::getMemspec(tdb, clk);
QString deviceType = memspec["memoryType"].toString();
if (deviceType == "DDR3") {
return DDR3TimeDependencies::getPossiblePhases();
} else {
// TODO maybe throw?
throw std::invalid_argument("Could not find the device type '" + deviceType.toStdString() + '\'');
}
}
bool DRAMTimeDependencyFactory::deviceSupported(const TraceDB& tdb) {
uint clk; // Not used
const QJsonObject& memspec = DRAMTimeDependenciesIF::getMemspec(tdb, clk);
QString deviceType = memspec["memoryType"].toString();
if (deviceType == "DDR3") {
return true;
} else {
return false;
}
}

View File

@@ -11,6 +11,10 @@ class DRAMTimeDependencyFactory {
public:
static std::shared_ptr<DRAMTimeDependenciesIF> make(const TraceDB& tdb);
static const std::vector<QString> possiblePhases(const TraceDB& tdb);
static bool deviceSupported(const TraceDB& tdb);
private:
DRAMTimeDependencyFactory() = delete;
~DRAMTimeDependencyFactory() = delete;

View File

@@ -6,23 +6,28 @@ PhaseDependenciesTracker::calculateDependencies(TraceDB& tdb, std::vector<QStrin
mBeginTransaction(tdb);
mDropTable(tdb);
mCreateTable(tdb);
auto& phases = mGetAllPhases(tdb, commands);
if (phases.size() == 0) {
mRollbackChanges(tdb);
if (commands.size() > 0) {
mCreateTable(tdb);
auto& phases = mGetAllPhases(tdb, commands);
if (phases.size() != 0) {
auto& entries = mCalculateDependencies(tdb, phases, commands);
mInsertIntoTable(tdb, entries);
} else {
// mRollbackChanges(tdb);
// return;
}
}
auto& entries = mCalculateDependencies(tdb, phases, commands);
mInsertIntoTable(tdb, entries);
mCommitTransaction(tdb);
}
void PhaseDependenciesTracker::mDropTable(TraceDB& tdb) {
QString command = "DROP TABLE DirectDependencies; ";
QString command = "DROP TABLE IF EXISTS DirectDependencies; ";
auto query = mExecuteQuery(tdb, command);
query.finish();
@@ -54,7 +59,8 @@ void PhaseDependenciesTracker::mInsertIntoTable(TraceDB& tdb, const std::vector<
// Write last entry and submit
mAddEntryCommandString(command, entry);
mExecuteQuery(tdb, command);
auto query = mExecuteQuery(tdb, command);
query.finish();
counter = 0;
@@ -70,7 +76,8 @@ void PhaseDependenciesTracker::mInsertIntoTable(TraceDB& tdb, const std::vector<
}
if (counter != 0) {
mExecuteQuery(tdb, command);
auto query = mExecuteQuery(tdb, command);
query.finish();
}
}
@@ -93,6 +100,9 @@ PhaseDependenciesTracker::mGetAllPhases(TraceDB& tdb, const std::vector<QString>
auto query = mExecuteQuery(tdb, queryStr);
if (!query.next())
return phases;
if (!query.last()) {
throw sqlException( ("Query:\n " + tdb.queryToString(query) + "\n failed. Error: \n"
"Could not retrieve number of rows\n").toStdString(),
@@ -128,6 +138,8 @@ PhaseDependenciesTracker::mGetAllPhases(TraceDB& tdb, const std::vector<QString>
throw std::runtime_error("An error occurred while fetching phases in 'PhaseDependenciesTracker::mGetAllPhases': expected " + std::to_string(nrows) + " rows, but found " + std::to_string(rowIt) + "\n");
}
query.finish();
return phases;
}
@@ -243,20 +255,20 @@ QSqlQuery PhaseDependenciesTracker::mExecuteQuery(TraceDB& tdb, const QString qu
void PhaseDependenciesTracker::mBeginTransaction(TraceDB& tdb) {
const QString queryStr = "BEGIN TRANSACTION;";
mExecuteQuery(tdb, queryStr);
auto query = mExecuteQuery(tdb, queryStr);
query.finish();
}
void PhaseDependenciesTracker::mRollbackChanges(TraceDB& tdb) {
const QString queryStr = "ROLLBACK;";
mExecuteQuery(tdb, queryStr);
auto query = mExecuteQuery(tdb, queryStr);
query.finish();
}
void PhaseDependenciesTracker::mCommitTransaction(TraceDB& tdb) {
const QString queryStr = "COMMIT;";
mExecuteQuery(tdb, queryStr);
auto query = mExecuteQuery(tdb, queryStr);
query.finish();
}
void PhaseDependenciesTracker::mAddFirstEntryCommandString(QString& command, const DBDependencyEntry& entry) {

View File

@@ -63,7 +63,7 @@ struct TransactionQueryTexts {
"WITH timespanTransactions AS (" + selectTransactionsByTimespan +
") SELECT * from DirectDependencies WHERE DelayedPhaseID IN ("
" SELECT DirectDependencies.DelayedPhaseID FROM DirectDependencies JOIN timespanTransactions "
" ON DirectDependencies.DelayedPhaseID = timespanTransactions.PhaseID )";
" ON DirectDependencies.DelayedPhaseID = timespanTransactions.PhaseID ) ";
// For some reason I could not use a parameter for these below
selectDependencyTypePercentages =
@@ -79,7 +79,7 @@ struct TransactionQueryTexts {
") "
"SELECT param, ROUND(ndeps*100.0 / (SELECT total FROM TotalDeps), 3) as percentage "
"FROM DependencyTypeDeps "
"ORDER BY percentage DESC ";
"ORDER BY percentage DESC ;";
selectTimeDependencyPercentages =
"WITH TotalDeps (total) AS ( "
@@ -94,7 +94,7 @@ struct TransactionQueryTexts {
") "
"SELECT param, ROUND(ndeps*100.0 / (SELECT total FROM TotalDeps), 3) as percentage "
"FROM DependencyTypeDeps "
"ORDER BY percentage DESC ";
"ORDER BY percentage DESC ;";
selectDelayedPhasePercentages =
"WITH TotalDeps (total) AS ( "
@@ -109,7 +109,7 @@ struct TransactionQueryTexts {
") "
"SELECT param, ROUND(ndeps*100.0 / (SELECT total FROM TotalDeps), 3) as percentage "
"FROM DependencyTypeDeps "
"ORDER BY percentage DESC ";
"ORDER BY percentage DESC ;";
selectDependencyPhasePercentages =
"WITH TotalDeps (total) AS ( "
@@ -124,7 +124,7 @@ struct TransactionQueryTexts {
") "
"SELECT param, ROUND(ndeps*100.0 / (SELECT total FROM TotalDeps), 3) as percentage "
"FROM DependencyTypeDeps "
"ORDER BY percentage DESC ";
"ORDER BY percentage DESC ;";
}
};

View File

@@ -67,7 +67,10 @@ TraceDB::TraceDB(QString path, bool openExisting)
database = QSqlDatabase::addDatabase("QSQLITE", path);
database.setDatabaseName(path);
database.open();
if (!database.open())
{
qDebug() << database.lastError().text();
}
if (!openExisting)
dropAndCreateTables();
prepareQueries();
@@ -399,6 +402,7 @@ DependencyInfos TraceDB::getDependencyInfos(DependencyInfos::Type infoType)
executeQuery(checkDependenciesExist);
if (!checkDependenciesExist.next() || checkDependenciesExist.value(0).toInt() != 1)
{
checkDependenciesExist.finish();
return dummy;
}
@@ -562,6 +566,8 @@ DependencyInfos TraceDB::parseDependencyInfos(QSqlQuery &query, const Dependency
infos.addInfo({query.value(0).toString(), query.value(1).toFloat()});
}
query.finish();
return infos;
}
@@ -576,6 +582,7 @@ void TraceDB::executeQuery(QSqlQuery query)
}
else {
query.finish();
throw sqlException( ("Query:\n " + queryToString(query) + "\n failed. Error: \n"
+
query.lastError().text()).toStdString(), this->pathToDB.toStdString());

View File

@@ -513,6 +513,9 @@ void TracePlot::currentTraceTimeChanged()
}
setAxisScale(xBottom, GetCurrentTimespan().Begin(), GetCurrentTimespan().End());
dependenciesSubMenu->setEnabled(navigator->TraceFile().checkDependencyTableExists());
replot();
}

View File

@@ -85,6 +85,8 @@ TraceFileTab::TraceFileTab(QWidget *parent, const QString &path)
setUpTraceSelector();
setUpCommentView();
setUpPossiblePhases();
ui->mcConfigView->setModel(mcConfigModel);
ui->mcConfigView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
@@ -184,6 +186,18 @@ void TraceFileTab::setUpCommentView()
commentModel, &CommentModel::rowDoubleClicked);
}
void TraceFileTab::setUpPossiblePhases() {
const auto possiblePhases = DRAMTimeDependencyFactory::possiblePhases(navigator->TraceFile());
for (auto p : possiblePhases) {
auto item = new QListWidgetItem(p, ui->depTabPossiblePhases);
item->setFlags(item->flags() | Qt::ItemIsUserCheckable); // set checkable flag
item->setCheckState(Qt::Unchecked); // AND initialize check state
}
ui->calculateDependencies->setEnabled(DRAMTimeDependencyFactory::deviceSupported(navigator->TraceFile()));
}
void TraceFileTab::tracefileChanged()
{
if (savingChangesToDB == true) {
@@ -305,21 +319,17 @@ void TraceFileTab::on_latencyTreeView_doubleClicked(const QModelIndex &index)
}
void TraceFileTab::on_calculateDependencies_clicked() {
// TODO - anything else? Update view maybe?
// TODO - For now fixed, but must be selectable
std::vector<QString> dependencyFilter = {
"ACT",
"PREPB",
"RD",
"RDA",
"WR",
"WRA",
"PDE",
"PDX",
"PREAB"
};
std::vector<QString> dependencyFilter;
for (int row = 0; row < ui->depTabPossiblePhases->count(); row++) {
auto item = ui->depTabPossiblePhases->item(row);
if (item->checkState() == Qt::Checked)
dependencyFilter.push_back(item->text());
}
PhaseDependenciesTracker::calculateDependencies(navigator->TraceFile(), dependencyFilter);
depInfosView = new DependencyInfosModel(navigator->TraceFile(), this);
ui->depInfosView->setModel(depInfosView);
ui->depInfosView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
}

View File

@@ -47,6 +47,7 @@
#include "presentation/traceplot.h"
#include "presentation/tracescroller.h"
#include "businessObjects/configmodels.h"
#include "businessObjects/dependencymodels.h"
class CommentModel;
@@ -66,6 +67,8 @@ public:
void setUpTraceplotScrollbar();
void setUpTraceSelector();
void setUpCommentView();
void setUpPossiblePhases();
void initNavigatorAndItsDependentWidgets(QString path);
QString getPathToTraceFile()
{

View File

@@ -209,16 +209,20 @@
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_depInfos">
<item>
<widget class="QPushButton" name="calculateDependencies">
<property name="text">
<string>Calculate Dependencies</string>
<widget class="QTreeView" name="depInfosView">
<property name="uniformRowHeights">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="depInfosView">
<property name="uniformRowHeights">
<bool>true</bool>
<widget class="QListWidget" name="depTabPossiblePhases">
</widget>
</item>
<item>
<widget class="QPushButton" name="calculateDependencies">
<property name="text">
<string>Calculate Dependencies</string>
</property>
</widget>
</item>