diff --git a/DRAMSys/traceAnalyzer/CMakeLists.txt b/DRAMSys/traceAnalyzer/CMakeLists.txt index 96594a93..361f8553 100644 --- a/DRAMSys/traceAnalyzer/CMakeLists.txt +++ b/DRAMSys/traceAnalyzer/CMakeLists.txt @@ -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 diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp index 4f89bf0f..17a46d4e 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp @@ -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(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(0.05 * clk) : 0; + + size_t invisibleDeps = 0; + + QPoint depLineTo(static_cast(xMap.transform(begin/* + (end + offset - begin)/4*/)), static_cast(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(xMap.transform(begin + (end + offset - begin)/2)), static_cast(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> Phase::getTracePlotLines(const Trace % drawingProperties.banksPerGroup); } } + +void Phase::addDependency(std::shared_ptr dependency) { + _dependencies.push_back(dependency); +} diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h index df6185aa..87c819ef 100644 --- a/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phase.h @@ -41,6 +41,7 @@ #include "presentation/util/colorgenerator.h" #include "presentation/tracedrawingproperties.h" #include "businessObjects/timespan.h" +#include "businessObjects/phases/phasedependency.h" #include #include #include @@ -75,6 +76,8 @@ public: } virtual QString Name() const = 0; + void addDependency(std::shared_ptr dependency); + protected: ID id; Timespan span; @@ -82,6 +85,8 @@ protected: std::weak_ptr transaction; std::vector spansOnCommandBus; std::shared_ptr spanOnDataBus; + std::vector> _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> getTracePlotLines(const TraceDrawingProperties &drawingProperties) const; @@ -103,6 +113,8 @@ protected: { return Granularity::Bankwise; } + + friend class PhaseDependency; }; class REQ : public Phase diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.cpp b/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.cpp new file mode 100644 index 00000000..05bbdc61 --- /dev/null +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.cpp @@ -0,0 +1,98 @@ +#include "phasedependency.h" +#include "phase.h" +#include + +PhaseDependency::PhaseDependency(DependencyType type, QString timeDependency, std::shared_ptr 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(0.05 * _dependency->clk) : 0; + + double depYVal = yMap.transform(depY); + double depSymbolHeight = yMap.transform(0) - yMap.transform(_dependency->hexagonHeight); + QPoint depLineFrom(static_cast(xMap.transform(depBegin/* + (depEnd + depOffset - depBegin)/4*/)), static_cast(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 + ); + + } +} \ No newline at end of file diff --git a/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.h b/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.h new file mode 100644 index 00000000..34fc4ec0 --- /dev/null +++ b/DRAMSys/traceAnalyzer/businessObjects/phases/phasedependency.h @@ -0,0 +1,41 @@ +#pragma once + +#include "presentation/tracedrawingproperties.h" +#include "businessObjects/timespan.h" + +#include +#include +#include +#include +#include + +class Phase; + +enum DependencyType { + Bank, Rank, InterRank +}; + +class PhaseDependency +{ + public: + PhaseDependency(DependencyType type, QString timeDependency, std::shared_ptr 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 _dependency; + + bool _isInvisible = false; + + void _draw(QPoint& end, double depY, const TraceDrawingProperties &drawingProperties, + bool drawtext, QPainter *painter, const QwtScaleMap &xMap, + const QwtScaleMap &yMap); +}; diff --git a/DRAMSys/traceAnalyzer/data/QueryTexts.h b/DRAMSys/traceAnalyzer/data/QueryTexts.h index 4101d106..9ff3d2a5 100644 --- a/DRAMSys/traceAnalyzer/data/QueryTexts.h +++ b/DRAMSys/traceAnalyzer/data/QueryTexts.h @@ -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 )"; + + } }; diff --git a/DRAMSys/traceAnalyzer/data/tracedb.cpp b/DRAMSys/traceAnalyzer/data/tracedb.cpp index a30c3c77..2a3ace91 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.cpp +++ b/DRAMSys/traceAnalyzer/data/tracedb.cpp @@ -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 &comments) @@ -133,9 +139,25 @@ vector> 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 TraceDB::getTransactionByID(ID id) @@ -381,8 +403,13 @@ shared_ptr TraceDB::parseTransactionFromQuery(QSqlQuery &query) } vector> TraceDB::parseTransactionsFromQuery( - QSqlQuery &query) + QSqlQuery &query, + bool updateVisiblePhases) { + if (updateVisiblePhases) { + _visiblePhases.clear(); + } + vector> result; bool firstIteration = true; @@ -416,12 +443,68 @@ vector> 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( + new PhaseDependency( + type, + timeDependencyStr, + _visiblePhases[dependencyID] + ) + ) + ); + + } else { + + _visiblePhases[delayedID]->addDependency( + std::shared_ptr( + new PhaseDependency( + type, + timeDependencyStr + ) + ) + ); + + } + + } else { + // TODO delayed phase not visible? + } + + } +} + vector TraceDB::parseCommentsFromQuery(QSqlQuery &query) { vector result; diff --git a/DRAMSys/traceAnalyzer/data/tracedb.h b/DRAMSys/traceAnalyzer/data/tracedb.h index 18abb1ae..ef9a8454 100644 --- a/DRAMSys/traceAnalyzer/data/tracedb.h +++ b/DRAMSys/traceAnalyzer/data/tracedb.h @@ -71,6 +71,7 @@ public: void updateComments(const std::vector &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 getNextActb(ID currentTransactionId); // std::shared_ptr getNextRefb(ID currentTransactionId); + void _updateDependenciesFromQuery(QSqlQuery &query); std::shared_ptr 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 parseTransactionFromQuery(QSqlQuery &query); std::vector> parseTransactionsFromQuery( - QSqlQuery &query); + QSqlQuery &query, + bool updateVisiblePhases = false); std::vector 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> _visiblePhases; // Updated at parseTransactionsFromQuery }; diff --git a/DRAMSys/traceAnalyzer/mainwindow.cpp b/DRAMSys/traceAnalyzer/mainwindow.cpp index 2b0ba7bd..8b68f2c3 100644 --- a/DRAMSys/traceAnalyzer/mainwindow.cpp +++ b/DRAMSys/traceAnalyzer/mainwindow.cpp @@ -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(), diff --git a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp index 03f96539..7adbcc69 100644 --- a/DRAMSys/traceAnalyzer/presentation/traceplot.cpp +++ b/DRAMSys/traceAnalyzer/presentation/traceplot.cpp @@ -448,6 +448,8 @@ void TracePlot::currentTraceTimeChanged() { transactions = navigator->TraceFile().getTransactionsInTimespan( GetCurrentTimespan()); + navigator->TraceFile().updateDependenciesInTimespan(GetCurrentTimespan()); + setAxisScale(xBottom, GetCurrentTimespan().Begin(), GetCurrentTimespan().End()); replot(); } diff --git a/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp b/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp index 564df655..03803b87 100644 --- a/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp +++ b/DRAMSys/traceAnalyzer/presentation/tracescroller.cpp @@ -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(); }