/* * 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 #include #include #include #include #include #include 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::Unchecked); // 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(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 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 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* intervals = new QVector; 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* samples = new QVector; 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* samples2 = new QVector; 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* samples3 = new QVector; 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(); }