Added dependency visualizations.

This commit is contained in:
Iron Prando da Silva
2021-10-18 10:42:47 +02:00
parent 2b43eafa60
commit 166ec66a92
11 changed files with 317 additions and 6 deletions

View File

@@ -90,6 +90,7 @@ add_executable(TraceAnalyzer
businessObjects/tracetestresults.cpp
presentation/tracemetrictreewidget.cpp
businessObjects/phases/phase.cpp
businessObjects/phases/phasedependency.cpp
presentation/tracedrawingproperties.cpp
presentation/util/traceplotline.cpp
presentation/util/traceplotlinecache.cpp

View File

@@ -67,9 +67,22 @@ void Phase::draw(QPainter *painter, const QwtScaleMap &xMap,
for (auto line : getTracePlotLines(drawingProperties))
{
if (!line->isCollapsed())
if (!line->isCollapsed()) {
drawPhaseSymbol(span.Begin(), span.End(), line->getYVal(),
drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap);
if (getGranularity() == Granularity::Bankwise) {
bool drawAllDependencies = false;
bool drawDependencies = true;
bool drawDependencyText = true;
if (drawAllDependencies || (highlight && drawDependencies)) {
drawPhaseDependencies(span.Begin(), span.End(), line->getYVal(),
drawingProperties, drawDependencyText, painter, xMap, yMap);
}
}
}
}
for (Timespan span : spansOnCommandBus)
@@ -116,6 +129,45 @@ void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y,
static_cast<int>(yVal + symbolHeight / 2)), TextPositioning::bottomRight);
}
void Phase::drawPhaseDependencies(traceTime begin, traceTime end, double y, const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap) const
{
QPen pen;
pen.setWidth(2);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing);
double yVal = yMap.transform(y);
double symbolHeight = yMap.transform(0) - yMap.transform(hexagonHeight);
traceTime offset = (begin == end) ? static_cast<traceTime>(0.05 * clk) : 0;
size_t invisibleDeps = 0;
QPoint depLineTo(static_cast<int>(xMap.transform(begin/* + (end + offset - begin)/4*/)), static_cast<int>(yVal));
for (auto dep : _dependencies) {
bool visible = false;
if (dep->isVisible()) {
if (!dep->draw(depLineTo, drawingProperties, drawtext, painter, xMap, yMap) ) {
invisibleDeps += 1;
}
} else {
invisibleDeps += 1;
}
}
if (invisibleDeps > 0) {
QPoint invisibleDepsPoint(static_cast<int>(xMap.transform(begin + (end + offset - begin)/2)), static_cast<int>(yVal + 0.1*symbolHeight));
drawText(painter, QString(std::to_string(invisibleDeps).c_str()), invisibleDepsPoint, TextPositioning::centerCenter);
}
}
QColor Phase::getColor(const TraceDrawingProperties &drawingProperties) const
{
switch (drawingProperties.colorGrouping) {
@@ -197,3 +249,7 @@ std::vector<std::shared_ptr<TracePlotLine>> Phase::getTracePlotLines(const Trace
% drawingProperties.banksPerGroup);
}
}
void Phase::addDependency(std::shared_ptr<PhaseDependency> dependency) {
_dependencies.push_back(dependency);
}

View File

@@ -41,6 +41,7 @@
#include "presentation/util/colorgenerator.h"
#include "presentation/tracedrawingproperties.h"
#include "businessObjects/timespan.h"
#include "businessObjects/phases/phasedependency.h"
#include <QString>
#include <QPainter>
#include <qwt_scale_map.h>
@@ -75,6 +76,8 @@ public:
}
virtual QString Name() const = 0;
void addDependency(std::shared_ptr<PhaseDependency> dependency);
protected:
ID id;
Timespan span;
@@ -82,6 +85,8 @@ protected:
std::weak_ptr<Transaction> transaction;
std::vector<Timespan> spansOnCommandBus;
std::shared_ptr<Timespan> spanOnDataBus;
std::vector<std::shared_ptr<PhaseDependency>> _dependencies;
double hexagonHeight;
TextPositioning captionPosition;
@@ -94,6 +99,11 @@ protected:
virtual void drawPhaseSymbol(traceTime begin, traceTime end, double y,
bool drawtext, PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap) const;
virtual void drawPhaseDependencies(traceTime begin, traceTime end, double y,
const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap) const;
virtual std::vector<std::shared_ptr<TracePlotLine>> getTracePlotLines(const TraceDrawingProperties &drawingProperties) const;
@@ -103,6 +113,8 @@ protected:
{
return Granularity::Bankwise;
}
friend class PhaseDependency;
};
class REQ : public Phase

View File

@@ -0,0 +1,98 @@
#include "phasedependency.h"
#include "phase.h"
#include <iostream>
PhaseDependency::PhaseDependency(DependencyType type, QString timeDependency, std::shared_ptr<Phase> dependency)
{
_type = type;
_timeDependency = timeDependency;
_dependency = dependency;
}
PhaseDependency::PhaseDependency(DependencyType type, QString timeDependency)
{
_type = type;
_timeDependency = timeDependency;
_dependency = nullptr;
_isInvisible = true;
}
PhaseDependency::~PhaseDependency()
{
}
bool PhaseDependency::draw(QPoint& end, const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap)
{
if (_isInvisible) return false;
traceTime depBegin = _dependency->span.Begin();
traceTime depEnd = _dependency->span.End();
if (xMap.transform(depEnd) < 0) return false;
bool drawn = false;
for (auto line : _dependency->getTracePlotLines(drawingProperties)) {
if (!line->isCollapsed()) {
_draw(end, line->getYVal(), drawingProperties, drawtext, painter, xMap, yMap);
drawn = true;
}
}
return drawn;
}
void PhaseDependency::_draw(QPoint& end, double depY, const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap)
{
traceTime depBegin = _dependency->span.Begin();
traceTime depEnd = _dependency->span.End();
traceTime depOffset = (depBegin == depEnd) ? static_cast<traceTime>(0.05 * _dependency->clk) : 0;
double depYVal = yMap.transform(depY);
double depSymbolHeight = yMap.transform(0) - yMap.transform(_dependency->hexagonHeight);
QPoint depLineFrom(static_cast<int>(xMap.transform(depBegin/* + (depEnd + depOffset - depBegin)/4*/)), static_cast<int>(depYVal));
QLineF line(depLineFrom, end);
double angle = std::atan2(-line.dy(), line.dx());
qreal arrowSize = 10;
QPointF arrowP1 = line.p2() - QPointF(sin(angle + M_PI / 3) * arrowSize, cos(angle + M_PI / 3) * arrowSize);
QPointF arrowP2 = line.p2() - QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize, cos(angle + M_PI - M_PI / 3) * arrowSize);
QPolygonF arrowHead;
arrowHead << line.p2() << arrowP1 << arrowP2;
QColor color = _dependency->getColor(drawingProperties);
painter->setBrush(QBrush(color, _dependency->getBrushStyle()));
painter->drawLine(line);
painter->drawPolygon(arrowHead);
if (drawtext) {
QPoint textPosition(line.x1() + (line.x2() - line.x1()) / 2, line.y1() + (line.y2() - line.y1()) / 2);
auto alignment = TextPositioning::topRight;
if (textPosition.y() == line.y1()) {
alignment = TextPositioning::topCenter;
} else if (textPosition.x() == line.x1()) {
if (line.y1() > line.y2()) {
alignment = TextPositioning::bottomRight;
}
}
drawText(
painter,
_timeDependency,
textPosition,
alignment
);
}
}

View File

@@ -0,0 +1,41 @@
#pragma once
#include "presentation/tracedrawingproperties.h"
#include "businessObjects/timespan.h"
#include <memory>
#include <QStringList>
#include <QString>
#include <QPainter>
#include <qwt_scale_map.h>
class Phase;
enum DependencyType {
Bank, Rank, InterRank
};
class PhaseDependency
{
public:
PhaseDependency(DependencyType type, QString timeDependency, std::shared_ptr<Phase> dependency);
PhaseDependency(DependencyType type, QString timeDependency);
~PhaseDependency();
bool isVisible() { return !_isInvisible; }
bool draw(QPoint& end, const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap);
protected:
DependencyType _type;
QString _timeDependency;
std::shared_ptr<Phase> _dependency;
bool _isInvisible = false;
void _draw(QPoint& end, double depY, const TraceDrawingProperties &drawingProperties,
bool drawtext, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap);
};

View File

@@ -42,6 +42,7 @@
struct TransactionQueryTexts {
QString queryHead;
QString selectTransactionsByTimespan, selectTransactionById;
QString checkDependenciesExist, selectDependenciesByTimespan;
TransactionQueryTexts()
{
@@ -53,6 +54,13 @@ struct TransactionQueryTexts {
" WHERE Ranges.end >= :begin AND Ranges.begin <= :end";
selectTransactionById = queryHead + " WHERE Transactions.ID = :id";
checkDependenciesExist = "SELECT CASE WHEN 0 < (SELECT count(*) FROM sqlite_master WHERE type = 'table' AND name = 'DirectDependencies') THEN 1 ELSE 0 END AS result";
selectDependenciesByTimespan = "WITH timespanTransactions AS (" + selectTransactionsByTimespan +
") SELECT * from DirectDependencies WHERE DelayedPhaseID IN ("
" SELECT DirectDependencies.DelayedPhaseID FROM DirectDependencies JOIN timespanTransactions "
" ON DirectDependencies.DelayedPhaseID = timespanTransactions.PhaseID )";
}
};

View File

@@ -85,6 +85,12 @@ void TraceDB::prepareQueries()
selectDebugMessagesByTimespan.prepare("SELECT time, Message FROM DebugMessages WHERE :begin <= time AND time <= :end ");
selectDebugMessagesByTimespanWithLimit = QSqlQuery(database);
selectDebugMessagesByTimespanWithLimit.prepare("SELECT time, Message FROM DebugMessages WHERE :begin <= time AND time <= :end LIMIT :limit");
checkDependenciesExist = QSqlQuery(database);
checkDependenciesExist.prepare(queryTexts.checkDependenciesExist);
selectDependenciesByTimespan = QSqlQuery(database);
selectDependenciesByTimespan.prepare(queryTexts.selectDependenciesByTimespan);
}
void TraceDB::updateComments(const std::vector<CommentModel::Comment> &comments)
@@ -133,9 +139,25 @@ vector<shared_ptr<Transaction>> TraceDB::getTransactionsInTimespan(
selectTransactionsByTimespan.bindValue(":begin", span.Begin());
selectTransactionsByTimespan.bindValue(":end", span.End());
executeQuery(selectTransactionsByTimespan);
return parseTransactionsFromQuery(selectTransactionsByTimespan);
return parseTransactionsFromQuery(selectTransactionsByTimespan, true);
}
void TraceDB::updateDependenciesInTimespan(const Timespan &span)
{
executeQuery(checkDependenciesExist);
if (checkDependenciesExist.next()) {
if (checkDependenciesExist.value(0).toInt() == 1) {
selectDependenciesByTimespan.bindValue(":begin", span.Begin());
selectDependenciesByTimespan.bindValue(":end", span.End());
executeQuery(selectDependenciesByTimespan);
_updateDependenciesFromQuery(selectDependenciesByTimespan);
}
}
}
//TODO Remove exception
shared_ptr<Transaction> TraceDB::getTransactionByID(ID id)
@@ -381,8 +403,13 @@ shared_ptr<Transaction> TraceDB::parseTransactionFromQuery(QSqlQuery &query)
}
vector<shared_ptr<Transaction>> TraceDB::parseTransactionsFromQuery(
QSqlQuery &query)
QSqlQuery &query,
bool updateVisiblePhases)
{
if (updateVisiblePhases) {
_visiblePhases.clear();
}
vector<shared_ptr<Transaction>> result;
bool firstIteration = true;
@@ -416,12 +443,68 @@ vector<shared_ptr<Transaction>> TraceDB::parseTransactionsFromQuery(
unsigned int phaseID = query.value(14).toInt();
QString phaseName = query.value(15).toString();
Timespan span(query.value(16).toLongLong(), query.value(17).toLongLong());
result.at(result.size() - 1)->addPhase(PhaseFactory::CreatePhase(phaseID,
phaseName, span, result.at(result.size() - 1), *this));
auto phase = PhaseFactory::CreatePhase(phaseID, phaseName, span, result.at(result.size() - 1), *this);
result.at(result.size() - 1)->addPhase(phase);
if (updateVisiblePhases) {
_visiblePhases[phaseID] = phase;
}
}
return result;
}
void TraceDB::_updateDependenciesFromQuery(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::Bank;
} else if (dependencyTypeStr == "rank") {
type = DependencyType::Rank;
} 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::shared_ptr<PhaseDependency>(
new PhaseDependency(
type,
timeDependencyStr,
_visiblePhases[dependencyID]
)
)
);
} else {
_visiblePhases[delayedID]->addDependency(
std::shared_ptr<PhaseDependency>(
new PhaseDependency(
type,
timeDependencyStr
)
)
);
}
} else {
// TODO delayed phase not visible?
}
}
}
vector<CommentModel::Comment> TraceDB::parseCommentsFromQuery(QSqlQuery &query)
{
vector<CommentModel::Comment> result;

View File

@@ -71,6 +71,7 @@ public:
void updateComments(const std::vector<CommentModel::Comment> &comments);
void updateFileDescription(const QString &description);
void updateDependenciesInTimespan(const Timespan &span);
void refreshData();
const GeneralInfo &getGeneralInfo() const
@@ -95,6 +96,7 @@ public:
// std::shared_ptr<Transaction> getNextActb(ID currentTransactionId);
// std::shared_ptr<Transaction> getNextRefb(ID currentTransactionId);
void _updateDependenciesFromQuery(QSqlQuery &query);
std::shared_ptr<Transaction> getTransactionByID(ID id);
ID getTransactionIDFromPhaseID(ID phaseID);
@@ -118,6 +120,8 @@ private:
QSqlQuery selectTransactionById;
QSqlQuery selectDebugMessagesByTimespan;
QSqlQuery selectDebugMessagesByTimespanWithLimit;
QSqlQuery checkDependenciesExist;
QSqlQuery selectDependenciesByTimespan;
TransactionQueryTexts queryTexts;
void prepareQueries();
@@ -125,7 +129,8 @@ private:
QString queryToString(QSqlQuery query);
std::shared_ptr<Transaction> parseTransactionFromQuery(QSqlQuery &query);
std::vector<std::shared_ptr<Transaction>> parseTransactionsFromQuery(
QSqlQuery &query);
QSqlQuery &query,
bool updateVisiblePhases = false);
std::vector<CommentModel::Comment> parseCommentsFromQuery(QSqlQuery &query);
void executeScriptFile(QString fileName);
@@ -135,6 +140,8 @@ private:
GeneralInfo *getGeneralInfoFromDB();
CommandLengths getCommandLengthsFromDB();
unsigned int getLengthOfCommandFromDB(const std::string& command);
std::map<unsigned int, std::shared_ptr<Phase>> _visiblePhases; // Updated at parseTransactionsFromQuery
};

View File

@@ -57,6 +57,7 @@ MainWindow::MainWindow(QWidget *parent) :
traceNavigator->GeneralTraceInfo().TraceSpan());
transactions = db->getTransactionsInTimespan(
traceNavigator->GeneralTraceInfo().TraceSpan());
db->updateDependenciesInTimespan(traceNavigator->GeneralTraceInfo().TraceSpan());
ui->qwtPlot->setAxisScale(QwtPlot::xBottom,
traceNavigator->GeneralTraceInfo().TraceSpan().Begin(),

View File

@@ -448,6 +448,8 @@ void TracePlot::currentTraceTimeChanged()
{
transactions = navigator->TraceFile().getTransactionsInTimespan(
GetCurrentTimespan());
navigator->TraceFile().updateDependenciesInTimespan(GetCurrentTimespan());
setAxisScale(xBottom, GetCurrentTimespan().Begin(), GetCurrentTimespan().End());
replot();
}

View File

@@ -196,6 +196,8 @@ void TraceScroller::currentTraceTimeChanged()
canvasClip->setInterval(spanOnTracePlot.Begin(), spanOnTracePlot.End());
Timespan span = GetCurrentTimespan();
transactions = navigator->TraceFile().getTransactionsInTimespan(span);
navigator->TraceFile().updateDependenciesInTimespan(span);
setAxisScale(xBottom, span.Begin(), span.End());
replot();
}