Files
DRAMSys/extensions/apps/traceAnalyzer/businessObjects/phases/phase.cpp

375 lines
12 KiB
C++

/*
* Copyright (c) 2015, Technische Universität Kaiserslautern
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
* Iron Prando da Silva
*/
#include "phase.h"
#include "businessObjects/traceplotlinemodel.h"
#include "businessObjects/transaction.h"
#include "presentation/tracedrawing.h"
#include <cmath>
void Phase::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect,
bool highlight, const TraceDrawingProperties &drawingProperties) const
{
Q_UNUSED(canvasRect);
QColor color = getColor(drawingProperties);
painter->setBrush(QBrush(getColor(drawingProperties), getBrushStyle()));
if (!drawingProperties.drawBorder)
{
painter->setPen(color);
}
else
{
painter->setPen(Qt::black);
}
if (highlight)
{
QPen pen(Qt::red);
pen.setWidth(3);
painter->setPen(pen);
}
for (auto yVal : getYVals(drawingProperties))
{
drawPhaseSymbol(span.Begin(), span.End(), yVal, drawingProperties.drawText, getPhaseSymbol(), painter, xMap,
yMap, drawingProperties.textColor);
DependencyOptions drawDependenciesOptions = drawingProperties.drawDependenciesOption;
if (drawDependenciesOptions.draw == DependencyOption::All ||
(drawDependenciesOptions.draw == DependencyOption::Selected && highlight))
{
drawPhaseDependencies(span.Begin(), span.End(), yVal, drawingProperties, painter, xMap, yMap);
}
}
for (Timespan spanOnCommandBus : spansOnCommandBus)
{
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type == AbstractTracePlotLineModel::RowCommandBusLine)
{
if (isColumnCommand())
continue;
}
else if (line->data.type == AbstractTracePlotLineModel::ColumnCommandBusLine)
{
if (!isColumnCommand())
continue;
}
else if (line->data.type != AbstractTracePlotLineModel::CommandBusLine)
continue;
drawPhaseSymbol(spanOnCommandBus.Begin(), spanOnCommandBus.End(), line->data.yVal, false, PhaseSymbol::Hexagon, painter, xMap, yMap,
drawingProperties.textColor);
}
}
if (spanOnDataStrobe.End() != 0)
{
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type == AbstractTracePlotLineModel::PseudoChannel0Line)
{
if (rank != 0)
continue;
}
else if (line->data.type == AbstractTracePlotLineModel::PseudoChannel1Line)
{
if (rank != 1)
continue;
}
else if (line->data.type != AbstractTracePlotLineModel::DataBusLine)
continue;
drawPhaseSymbol(spanOnDataStrobe.Begin(), spanOnDataStrobe.End(), line->data.yVal, false,
PhaseSymbol::Hexagon, painter, xMap, yMap, drawingProperties.textColor);
}
}
}
void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y, bool drawtext, PhaseSymbol symbol,
QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QColor& textColor) const
{
double yVal = yMap.transform(y);
double symbolHeight = yMap.transform(0) - yMap.transform(hexagonHeight);
// Increase display size of phases with zero span
traceTime offset = (begin == end) ? static_cast<traceTime>(0.05 * clk) : 0;
if (symbol == PhaseSymbol::Hexagon)
{
QPoint hexFrom(static_cast<int>(xMap.transform(begin)), static_cast<int>(yVal));
QPoint hexTo(static_cast<int>(xMap.transform(end + offset)), static_cast<int>(yVal));
drawHexagon(painter, hexFrom, hexTo, symbolHeight);
}
else
{
QPoint upperLeft(static_cast<int>(xMap.transform(begin)), static_cast<int>(yVal - symbolHeight / 2));
QPoint bottomRight(static_cast<int>(xMap.transform(end)), static_cast<int>(yVal + symbolHeight / 2));
painter->drawRect(QRect(upperLeft, bottomRight));
}
if (drawtext)
drawText(painter, Name(),
QPoint(static_cast<int>(xMap.transform(begin)), static_cast<int>(yVal + symbolHeight / 2)),
TextPositioning::bottomRight, textColor);
}
void Phase::drawPhaseDependencies(traceTime begin, traceTime end, double y,
const TraceDrawingProperties &drawingProperties, QPainter *painter,
const QwtScaleMap &xMap, const QwtScaleMap &yMap) const
{
QPen pen;
pen.setWidth(2);
painter->save();
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 (const auto& dep : mDependencies)
{
bool visible = false;
if (dep->isVisible())
{
if (!dep->draw(depLineTo, drawingProperties, 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::number(invisibleDeps), invisibleDepsPoint, TextPositioning::centerCenter);
}
painter->restore();
}
std::vector<int> Phase::getYVals(const TraceDrawingProperties &drawingProperties) const
{
std::vector<int> yVals;
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type != AbstractTracePlotLineModel::BankLine)
continue;
unsigned int yVal = line->data.yVal;
unsigned int drawnRank = line->data.rank;
unsigned int drawnBank = line->data.bank;
bool shouldBeDrawn = false;
switch (getGranularity())
{
case Granularity::Rankwise:
shouldBeDrawn = (rank == drawnRank);
break;
case Granularity::Groupwise:
shouldBeDrawn = (rank == drawnRank) && (bank % drawingProperties.banksPerGroup ==
drawnBank % drawingProperties.banksPerGroup);
break;
case Granularity::Bankwise:
shouldBeDrawn = (bank == drawnBank);
break;
case Granularity::TwoBankwise:
shouldBeDrawn = (bank == drawnBank) || ((bank + drawingProperties.per2BankOffset) == drawnBank);
break;
}
if (shouldBeDrawn)
yVals.push_back(yVal);
}
return yVals;
}
std::vector<int> REQ::getYVals(const TraceDrawingProperties &drawingProperties) const
{
std::vector<int> yVals;
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type != AbstractTracePlotLineModel::RequestLine)
continue;
yVals.push_back(line->data.yVal);
}
return yVals;
}
std::vector<int> RESP::getYVals(const TraceDrawingProperties &drawingProperties) const
{
std::vector<int> yVals;
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type != AbstractTracePlotLineModel::ResponseLine)
continue;
yVals.push_back(line->data.yVal);
}
return yVals;
}
QColor Phase::getColor(const TraceDrawingProperties &drawingProperties) const
{
switch (drawingProperties.colorGrouping) {
case ColorGrouping::PhaseType:
return getPhaseColor();
break;
case ColorGrouping::Thread:
return ColorGenerator::getColor(static_cast<unsigned int>(transaction.lock()->thread));
break;
case ColorGrouping::RainbowTransaction:
return ColorGenerator::getRainbowColored(transaction.lock()->id, ColorName::HSV15);
break;
case ColorGrouping::Transaction:
default:
return ColorGenerator::getColor(transaction.lock()->id);
}
}
Qt::BrushStyle Phase::getBrushStyle() const
{
return Qt::SolidPattern;
}
bool Phase::isSelected(Timespan timespan, double yVal, const TraceDrawingProperties &drawingProperties) const
{
if (span.overlaps(timespan))
{
for (auto lineYVal : getYVals(drawingProperties))
if (fabs(yVal - lineYVal) <= hexagonHeight / 2)
return true;
}
for (Timespan _span : spansOnCommandBus)
{
if (_span.overlaps(timespan))
{
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type == AbstractTracePlotLineModel::RowCommandBusLine)
{
if (isColumnCommand())
continue;
}
else if (line->data.type == AbstractTracePlotLineModel::ColumnCommandBusLine)
{
if (!isColumnCommand())
continue;
}
else if (line->data.type != AbstractTracePlotLineModel::CommandBusLine)
continue;
if (fabs(yVal - line->data.yVal) <= hexagonHeight / 2)
return true;
}
}
}
if (spanOnDataStrobe.End() != 0 && spanOnDataStrobe.overlaps(timespan))
{
for (const auto &line : drawingProperties.getTracePlotLines())
{
if (line->data.type == AbstractTracePlotLineModel::PseudoChannel0Line)
{
if (rank != 0)
continue;
}
else if (line->data.type == AbstractTracePlotLineModel::PseudoChannel1Line)
{
if (rank != 1)
continue;
}
else if (line->data.type != AbstractTracePlotLineModel::DataBusLine)
continue;
if (fabs(yVal - line->data.yVal) <= hexagonHeight / 2)
return true;
}
}
return false;
}
bool Phase::isColumnCommand() const
{
if (dynamic_cast<const RD *>(this) || dynamic_cast<const RDA *>(this) || dynamic_cast<const WR *>(this) ||
dynamic_cast<const WRA *>(this))
return true;
else
return false;
}
Phase::PhaseSymbol Phase::getPhaseSymbol() const
{
return PhaseSymbol::Hexagon;
}
void Phase::addDependency(const std::shared_ptr<PhaseDependency>& dependency)
{
mDependencies.push_back(dependency);
}