Files
DRAMSys/extensions/apps/traceAnalyzer/tracefiletab.cpp

299 lines
10 KiB
C++

/*
* Copyright (c) 2025 Fraunhofer IESE. All rights reserved.
*
* Authors:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
* Iron Prando da Silva
*/
#include "tracefiletab.h"
#include "businessObjects/dramTimeDependencies/phasedependenciestracker.h"
#include <QItemDelegate>
#include <QStandardItem>
#include <qwt_text.h>
#include <qwt_plot_curve.h>
#include <qwt_plot_histogram.h>
#include <qwt_plot_magnifier.h>
#include <qwt_plot_panner.h>
void TraceFileTab::setUpPossiblePhases()
{
const auto possiblePhases = ConfigurationFactory::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::Checked); // AND initialize check state
}
ui->calculateDependencies->setEnabled(
ConfigurationFactory::deviceSupported(navigator->TraceFile()));
}
class ItemDelegate : public QItemDelegate
{
public:
ItemDelegate(QObject* parent = nullptr) : QItemDelegate(parent) {}
void
paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
if (index.column() == 1)
{
double progress = index.data().toDouble();
QStyleOptionProgressBar opt;
opt.rect = option.rect;
opt.minimum = 0;
opt.maximum = 100;
opt.progress = static_cast<int>(floor(progress));
opt.text = QString::number(progress, 'f', 2) + " %";
opt.textVisible = true;
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &opt, painter, nullptr);
}
else
{
QItemDelegate::paint(painter, option, index);
}
}
};
void TraceFileTab::on_latencyTreeView_doubleClicked(const QModelIndex& index)
{
// Get onlye the leaf:
if (index.column() == 0 && index.model()->hasChildren(index) == false)
{
unsigned int id = index.data().toUInt();
if (id != 0)
{
navigator->selectTransaction(id);
}
}
}
void TraceFileTab::on_calculateDependencies_clicked()
{
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());
}
savingChangesToDB = true;
PhaseDependenciesTracker::calculateDependencies(navigator->TraceFile(), dependencyFilter);
depInfosView = new DependencyInfosModel(navigator->TraceFile(), this);
ui->depInfosView->setModel(depInfosView);
ui->depInfosView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
}
void TraceFileTab::on_startLatencyAnalysis_clicked()
{
// Setup Database:
QSqlDatabase db = navigator->TraceFile().getDatabase();
QSqlQuery query(db);
// Check the count of transactions:
QString sql = "SELECT COUNT(*) FROM Transactions;";
query.exec(sql);
query.next();
int maxTransactions = query.value(0).toInt();
// Create Database Setup and Query:
sql = "SELECT ((p2.PhaseEnd - p1.PhaseBegin)/1000) as latency, 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\" ORDER BY latency;";
query.exec(sql);
// Creatoe model and fill it from Database:
QStandardItemModel* model = new QStandardItemModel();
int currentLatency = 0;
QStandardItem* currentLatencyItem = nullptr;
int counter = 0;
while (query.next())
{
if (query.value(0) != currentLatency)
{
currentLatencyItem = new QStandardItem(QString::number(query.value(0).toInt()) + " ns");
currentLatency = query.value(0).toInt();
QList<QStandardItem*> row;
row.append(currentLatencyItem);
row.append(new QStandardItem());
model->appendRow(row);
}
QStandardItem* id = new QStandardItem(query.value(1).toString());
currentLatencyItem->appendRow(id);
counter++;
int percentage = int(ceil((double(counter)) / (double(maxTransactions)) * 100.0));
ui->latencyAnalysisProgressBar->setValue(percentage);
}
QStringList header = {"Latency", "Occurences"};
model->setHorizontalHeaderLabels(header);
// Generate Histrogram and Tree:
QwtPlotHistogram* hist = new QwtPlotHistogram;
QVector<QwtIntervalSample>* intervals = new QVector<QwtIntervalSample>;
for (int i = 0; i < model->rowCount(); i++)
{
double latency = model->item(i, 0)->text().replace(" ns", "").toDouble();
int numberOfChilds = model->item(i)->rowCount();
double percentage = 100 * ((double(numberOfChilds)) / (double(counter)));
model->item(i, 1)->setText(QString::number(percentage));
intervals->append(QwtIntervalSample(percentage, latency, latency + 1));
}
ui->latencyTreeView->setItemDelegate(new ItemDelegate(ui->latencyTreeView));
ui->latencyTreeView->setModel(model);
hist->setSamples(*intervals);
hist->attach(ui->latencyPlot);
hist->setPen(QPen(QColor(255, 0, 0, 100)));
hist->setBrush(QBrush(QColor(255, 0, 0, 255)));
ui->latencyPlot->setAxisTitle(0, "Occurences [%]");
QwtText axisTitle("Latency [ns]");
axisTitle.setFont(ui->latencyPlot->axisTitle(QwtPlot::xBottom).font());
ui->latencyPlot->setAxisTitle(QwtPlot::xBottom, axisTitle);
ui->latencyPlot->replot();
}
void TraceFileTab::on_startPowerAnalysis_clicked()
{
QSqlDatabase db = navigator->TraceFile().getDatabase();
QSqlQuery query(db);
QString sql = "SELECT time, AveragePower FROM Power;";
query.exec(sql);
QwtPointSeriesData* data = new QwtPointSeriesData;
QwtPlotCurve* cur = new QwtPlotCurve("Speed");
QVector<QPointF>* samples = new QVector<QPointF>;
double maxPower = 0.0;
while (query.next())
{
double time = query.value(0).toDouble();
double power = query.value(1).toDouble();
samples->push_back(QPointF(time, power));
maxPower = std::max(maxPower, power);
}
// ui->powerPlot->setAxisTitle(QwtPlot::xBottom,"Time");
// ui->powerPlot->setAxisLabelRotation(QwtPlot::xBottom,-50.0);
// ui->powerPlot->setAxisLabelAlignment(QwtPlot::xBottom,Qt::AlignLeft|Qt::AlignBottom);
// ui->powerPlot->setAxisTitle(QwtPlot::yLeft,"Power");
data->setSamples(*samples);
cur->setData(data);
cur->attach(ui->powerPlot);
cur->setPen(QPen(QColor(255, 0, 0)));
ui->powerPlot->setAxisTitle(0, "Power [mW]");
ui->powerPlot->setAxisScale(0, 0.0, maxPower);
QwtText axisTitle0("Time [s]");
axisTitle0.setFont(ui->powerPlot->axisTitle(QwtPlot::xBottom).font());
ui->powerPlot->setAxisTitle(QwtPlot::xBottom, axisTitle0);
QwtPlotMagnifier* mag1 = new QwtPlotMagnifier(ui->powerPlot->canvas());
mag1->setAxisEnabled(QwtPlot::xBottom, true);
mag1->setAxisEnabled(QwtPlot::yLeft, false);
mag1->setWheelFactor(5);
QwtPlotPanner* pan1 = new QwtPlotPanner(ui->powerPlot->canvas());
pan1->setAxisEnabled(QwtPlot::xBottom, true);
pan1->setAxisEnabled(QwtPlot::yLeft, false);
ui->powerPlot->replot();
// Bandwidth analysis:
sql = "SELECT time, AverageBandwidth FROM Bandwidth;";
query.exec(sql);
QwtPointSeriesData* data2 = new QwtPointSeriesData;
QwtPlotCurve* cur2 = new QwtPlotCurve("Speed");
QVector<QPointF>* samples2 = new QVector<QPointF>;
while (query.next())
{
double time = query.value(0).toDouble();
double percentage = query.value(1).toDouble() * 100.0;
samples2->push_back(QPointF(time, percentage));
}
data2->setSamples(*samples2);
cur2->setData(data2);
cur2->attach(ui->bandwidthPlot);
cur2->setPen(QPen(QColor(255, 0, 0)));
ui->bandwidthPlot->setAxisTitle(0, "Bandwidth [%]");
ui->bandwidthPlot->setAxisScale(0, 0.0, 100.0);
QwtText axisTitle2("Time [s]");
axisTitle2.setFont(ui->bandwidthPlot->axisTitle(QwtPlot::xBottom).font());
ui->bandwidthPlot->setAxisTitle(QwtPlot::xBottom, axisTitle2);
QwtPlotMagnifier* mag2 = new QwtPlotMagnifier(ui->bandwidthPlot->canvas());
mag2->setAxisEnabled(QwtPlot::xBottom, true);
mag2->setAxisEnabled(QwtPlot::yLeft, false);
mag2->setWheelFactor(5);
QwtPlotPanner* pan2 = new QwtPlotPanner(ui->bandwidthPlot->canvas());
pan2->setAxisEnabled(QwtPlot::xBottom, true);
pan2->setAxisEnabled(QwtPlot::yLeft, false);
ui->bandwidthPlot->replot();
// Buffer analysis:
// sql = "select max(BufferNumber) from BufferDepth;";
// query.exec(sql);
// query.next();
// unsigned int numberOfBuffers = query.value(0).toUInt();
sql = "select MaxBufferDepth from GeneralInfo;";
query.exec(sql);
query.next();
unsigned int maxBufferDepth = query.value(0).toUInt();
sql = "select Time, AverageBufferDepth from BufferDepth where BufferNumber = 0"; // TODO
query.exec(sql);
QwtPointSeriesData* data3 = new QwtPointSeriesData;
QwtPlotCurve* cur3 = new QwtPlotCurve("Speed");
QVector<QPointF>* samples3 = new QVector<QPointF>;
while (query.next())
{
double time = query.value(0).toDouble();
double queue = query.value(1).toDouble();
samples3->push_back(QPointF(time, queue));
}
data3->setSamples(*samples3);
cur3->setData(data3);
cur3->attach(ui->bufferPlot);
cur3->setPen(QPen(QColor(255, 0, 0)));
ui->bufferPlot->setAxisTitle(0, "Buffer Utilization");
ui->bufferPlot->setAxisScale(0, 0.0, maxBufferDepth);
QwtText axisTitle3("Time [s]");
axisTitle3.setFont(ui->bufferPlot->axisTitle(QwtPlot::xBottom).font());
ui->bufferPlot->setAxisTitle(QwtPlot::xBottom, axisTitle3);
QwtPlotMagnifier* mag3 = new QwtPlotMagnifier(ui->bufferPlot->canvas());
mag3->setAxisEnabled(QwtPlot::xBottom, true);
mag3->setAxisEnabled(QwtPlot::yLeft, false);
mag3->setWheelFactor(5);
QwtPlotPanner* pan3 = new QwtPlotPanner(ui->bufferPlot->canvas());
pan3->setAxisEnabled(QwtPlot::xBottom, true);
pan3->setAxisEnabled(QwtPlot::yLeft, false);
ui->bufferPlot->replot();
}