Files
DRAMSys/DRAMSys/traceAnalyzer/businessObjects/phases/phase.cpp
Derek Christ 2a0c7ae771 Fix a memory leak in TraceAnalyzer
A memory leak was fixed by replacing std::shared_ptr with std::weak_ptr
in phase.h and phase.cpp for the pointer to its transaction.
Not checking if the transaction is still valid is ok, because the
transaction outlives the phase.
2021-06-30 16:25:38 +02:00

211 lines
8.1 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
*/
#include "phase.h"
#include "presentation/tracedrawing.h"
#include "businessObjects/transaction.h"
#include <cmath>
using namespace std;
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);
}
if (!isCollapsed(drawingProperties))
{
if (getGranularity() == Granularity::Rankwise)
{
for (int i = getYVal(drawingProperties); i < (int)(getYVal(drawingProperties) + drawingProperties.banksPerRank); i++)
drawPhaseSymbol(span.Begin(), span.End(), i, drawingProperties.drawText,
getPhaseSymbol(), painter, xMap, yMap);
}
else if (getGranularity() == Granularity::Groupwise)
{
for (int i = getYVal(drawingProperties); i < (int)(getYVal(drawingProperties) + drawingProperties.banksPerRank); i += drawingProperties.banksPerGroup)
drawPhaseSymbol(span.Begin(), span.End(), i, drawingProperties.drawText,
getPhaseSymbol(), painter, xMap, yMap);
}
else // if (getGranularity() == Granularity::Bankwise)
drawPhaseSymbol(span.Begin(), span.End(), getYVal(drawingProperties),
drawingProperties.drawText, getPhaseSymbol(), painter, xMap, yMap);
}
for (Timespan span : spansOnCommandBus)
{
drawPhaseSymbol(span.Begin(), span.End(), drawingProperties.yValCommandBus,
false, PhaseSymbol::Hexagon, painter, xMap, yMap);
}
if (spanOnDataBus)
{
drawPhaseSymbol(spanOnDataBus->Begin(), spanOnDataBus->End(), drawingProperties.yValDataBus,
false, PhaseSymbol::Hexagon, painter, xMap, yMap);
}
}
void Phase::drawPhaseSymbol(traceTime begin, traceTime end, double y,
bool drawtext, PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap,
const QwtScaleMap &yMap) 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);
}
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::Transaction:
default:
return ColorGenerator::getColor(transaction.lock()->id);
}
}
int Phase::getYVal(const TraceDrawingProperties &drawingProperties) const
{
if (getGranularity() == Granularity::Bankwise)
return drawingProperties.getYValOfBank(transaction.lock()->bank);
else if (getGranularity() == Granularity::Groupwise)
return drawingProperties.getYValOfBankGroup(transaction.lock()->rank, transaction.lock()->bank);
else // if (getGranularity() == Granularity::Rankwise)
return drawingProperties.getYValOfRank(transaction.lock()->rank);
}
Qt::BrushStyle Phase::getBrushStyle() const
{
return Qt::SolidPattern;
}
bool Phase::isSelected(traceTime time, double yVal,
const TraceDrawingProperties &drawingProperties) const
{
// Increase selectable area of phases with zero span
traceTime offset = (span.Begin() == span.End()) ? static_cast<traceTime>(0.05 * clk) : 0;
if (span.Begin() <= time && time <= (span.End() + offset))
{
if (getGranularity() == Granularity::Bankwise)
{
if (fabs(yVal - getYVal(drawingProperties)) <= hexagonHeight)
return true;
}
else if (getGranularity() == Granularity::Groupwise)
{
for (int offset = 0; offset < drawingProperties.banksPerRank; offset += drawingProperties.banksPerGroup)
{
if (fabs(yVal - (getYVal(drawingProperties) + offset)) <= hexagonHeight)
return true;
}
}
else // if (getGranularity() == Granularity::Rankwise)
{
for (int offset = 0; offset < drawingProperties.banksPerRank; offset++)
{
if (fabs(yVal - (getYVal(drawingProperties) + offset)) <= hexagonHeight)
return true;
}
}
}
if (spanOnDataBus && spanOnDataBus->contains(time) && fabs(yVal - drawingProperties.yValDataBus) <= hexagonHeight)
return true;
for (Timespan span : spansOnCommandBus) {
if (span.contains(time)
&& fabs(yVal - drawingProperties.yValCommandBus) <= hexagonHeight)
return true;
}
return false;
}
Phase::PhaseSymbol Phase::getPhaseSymbol() const
{
return PhaseSymbol::Hexagon;
}
bool Phase::isCollapsed(const TraceDrawingProperties &drawingProperties) const
{
// Never discard REQ and RESP phases
if (dynamic_cast<const REQ *>(this) != nullptr || dynamic_cast<const RESP *>(this) != nullptr)
return false;
return drawingProperties.getRankCollapsedState(transaction.lock()->rank);
}