Merge branch 'master' of git.rhrk.uni-kl.de:EIT-Wehn/dram.vp.system
Conflicts: dram/dramSys/dramSys.pro dram/resources/scripts/metrics.py dram/src/common/libDRAMPower.cpp
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,7 @@
|
||||
/debug
|
||||
/release
|
||||
/dram/debug
|
||||
/dram/release
|
||||
*.tdb
|
||||
*.tdb-journal
|
||||
*.out
|
||||
|
||||
1
analyzer/.gitignore
vendored
Normal file
1
analyzer/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
build*
|
||||
2
analyzer/analyzer/.gitignore
vendored
Normal file
2
analyzer/analyzer/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
traceAnalyzer.pro.user
|
||||
traceAnalyzer.pro.user.*
|
||||
2
analyzer/analyzer/README.md
Normal file
2
analyzer/analyzer/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
dram.vp.scheduler
|
||||
=================
|
||||
19
analyzer/analyzer/businessObjects/calculatedMetric.h
Normal file
19
analyzer/analyzer/businessObjects/calculatedMetric.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef METRIC_H
|
||||
#define METRIC_H
|
||||
#include <QString>
|
||||
|
||||
class CalculatedMetric
|
||||
{
|
||||
public:
|
||||
CalculatedMetric(QString name, double value): name(name),value(value){}
|
||||
QString getName(){return name;}
|
||||
double getValue(){return value;}
|
||||
|
||||
private:
|
||||
QString name;
|
||||
double value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // METRIC_H
|
||||
16
analyzer/analyzer/businessObjects/comment.h
Normal file
16
analyzer/analyzer/businessObjects/comment.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef COMMENT_H
|
||||
#define COMMENT_H
|
||||
#include <QString>
|
||||
#include "timespan.h"
|
||||
|
||||
class Comment
|
||||
{
|
||||
traceTime time;
|
||||
QString text;
|
||||
public:
|
||||
Comment(traceTime time,QString text):time(time),text(text){}
|
||||
traceTime Time() const{return time;}
|
||||
const QString& Text() const{return text;}
|
||||
};
|
||||
|
||||
#endif // COMMENT_H
|
||||
25
analyzer/analyzer/businessObjects/generalinfo.h
Normal file
25
analyzer/analyzer/businessObjects/generalinfo.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef GENERALINFO_H
|
||||
#define GENERALINFO_H
|
||||
#include "timespan.h"
|
||||
#include <QString>
|
||||
|
||||
struct GeneralInfo
|
||||
{
|
||||
unsigned int numberOfTransactions;
|
||||
unsigned int numberOfPhases;
|
||||
Timespan span;
|
||||
unsigned int numberOfBanks;
|
||||
QString description;
|
||||
QString unitOfTime;
|
||||
unsigned int clkPeriod;
|
||||
|
||||
public:
|
||||
GeneralInfo(unsigned int numberOfTransactions,unsigned int numberOfPhases, Timespan span,unsigned int numberOfBanks,const QString& description, QString unitOfTime,unsigned int clkPeriod) :
|
||||
numberOfTransactions(numberOfTransactions) , numberOfPhases(numberOfPhases), span(span), numberOfBanks(numberOfBanks), description(description), unitOfTime(unitOfTime),clkPeriod(clkPeriod)
|
||||
{
|
||||
}
|
||||
|
||||
GeneralInfo(){}
|
||||
};
|
||||
|
||||
#endif // GENERALINFO_H
|
||||
111
analyzer/analyzer/businessObjects/phases/phase.cpp
Normal file
111
analyzer/analyzer/businessObjects/phases/phase.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#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);
|
||||
}
|
||||
|
||||
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(hexagonHeigth);
|
||||
|
||||
if(symbol == PhaseSymbol::Hexagon)
|
||||
{
|
||||
QPoint hexFrom(xMap.transform(begin),yVal);
|
||||
QPoint hexTo(xMap.transform(end),yVal);
|
||||
drawHexagon(painter, hexFrom, hexTo, symbolHeight);
|
||||
}
|
||||
else
|
||||
{
|
||||
QPoint upperLeft(xMap.transform(begin),yVal-symbolHeight/2);
|
||||
QPoint bottomRight(xMap.transform(end),yVal+symbolHeight/2);
|
||||
painter->drawRect(QRect(upperLeft,bottomRight));
|
||||
}
|
||||
|
||||
if(drawtext)
|
||||
drawText(painter,Name(), QPoint(xMap.transform(begin), 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->Thread()));
|
||||
break;
|
||||
case ColorGrouping::Transaction:
|
||||
default:
|
||||
return ColorGenerator::getColor(transaction->Id());
|
||||
}
|
||||
}
|
||||
|
||||
int Phase::getYVal(const TraceDrawingProperties &drawingProperties) const
|
||||
{
|
||||
Q_UNUSED(drawingProperties)
|
||||
return transaction->Bank();
|
||||
}
|
||||
|
||||
Qt::BrushStyle Phase::getBrushStyle() const
|
||||
{
|
||||
return Qt::SolidPattern;
|
||||
}
|
||||
|
||||
bool Phase::isSelected(traceTime time, double yVal, const TraceDrawingProperties& drawingproperties) const
|
||||
{
|
||||
if (span.contains(time) && fabs(yVal-getYVal(drawingproperties))<=hexagonHeigth)
|
||||
return true;
|
||||
if (spanOnDataBus && spanOnDataBus->contains(time) && fabs(yVal-drawingproperties.yValDataBus)<=hexagonHeigth)
|
||||
return true;
|
||||
|
||||
for(Timespan span: spansOnCommandBus)
|
||||
{
|
||||
if (span.contains(time) && fabs(yVal-drawingproperties.yValCommandBus)<=hexagonHeigth)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Phase::PhaseSymbol Phase::getPhaseSymbol() const
|
||||
{
|
||||
return PhaseSymbol::Hexagon;
|
||||
}
|
||||
186
analyzer/analyzer/businessObjects/phases/phase.h
Normal file
186
analyzer/analyzer/businessObjects/phases/phase.h
Normal file
@@ -0,0 +1,186 @@
|
||||
#ifndef BANKPHASE_H
|
||||
#define BANKPHASE_H
|
||||
#include "presentation/util/colorgenerator.h"
|
||||
#include "presentation/tracedrawingproperties.h"
|
||||
#include "businessObjects/timespan.h"
|
||||
#include <QString>
|
||||
#include <QPainter>
|
||||
#include <qwt_scale_map.h>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
typedef unsigned int ID;
|
||||
enum TextPositioning;
|
||||
class Transaction;
|
||||
|
||||
class Phase
|
||||
{
|
||||
public:
|
||||
Phase(ID id,Timespan span,const std::shared_ptr<Transaction>& transaction, std::vector<Timespan> spansOnCommandBus, std::shared_ptr<Timespan> spanOnDataBus):
|
||||
id(id),span(span),transaction(transaction), spansOnCommandBus(spansOnCommandBus), spanOnDataBus(spanOnDataBus),
|
||||
hexagonHeigth(0.6), captionPosition(TextPositioning::bottomRight){}
|
||||
|
||||
void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, bool highlight,const TraceDrawingProperties& drawingProperties) const;
|
||||
bool isSelected(traceTime time, double yVal, const TraceDrawingProperties& drawingproperties) const;
|
||||
const Timespan& Span() const {return span;}
|
||||
ID Id() const {return id;}
|
||||
virtual QString Name() const = 0;
|
||||
|
||||
protected:
|
||||
ID id;
|
||||
Timespan span;
|
||||
std::shared_ptr<Transaction> transaction;
|
||||
std::vector<Timespan> spansOnCommandBus;
|
||||
std::shared_ptr<Timespan> spanOnDataBus;
|
||||
double hexagonHeigth;
|
||||
TextPositioning captionPosition;
|
||||
|
||||
enum PhaseSymbol {Hexagon,Rect};
|
||||
virtual PhaseSymbol getPhaseSymbol() const;
|
||||
virtual Qt::BrushStyle getBrushStyle() const;
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const;
|
||||
virtual int getYVal(const TraceDrawingProperties &drawingProperties) const;
|
||||
virtual QColor getPhaseColor() const = 0;
|
||||
virtual void drawPhaseSymbol(traceTime begin, traceTime end, double y,bool drawtext,PhaseSymbol symbol, QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap) const;
|
||||
|
||||
};
|
||||
|
||||
class REQ : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(1);}
|
||||
virtual QString Name() const final {return "REQ";}
|
||||
virtual int getYVal(const TraceDrawingProperties &drawingProperties) const override {return drawingProperties.yValRequest;}
|
||||
};
|
||||
|
||||
|
||||
class RESP : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(1);}
|
||||
virtual QString Name() const override {return "RESP";}
|
||||
virtual int getYVal(const TraceDrawingProperties &drawingProperties) const override {return drawingProperties.yValResponse;}
|
||||
|
||||
};
|
||||
|
||||
class PRE : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(1);}
|
||||
virtual QString Name() const override {return "PRE";}
|
||||
};
|
||||
|
||||
|
||||
class ACT : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(3);}
|
||||
virtual QString Name() const override {return "ACT";}
|
||||
};
|
||||
|
||||
class RD : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(4);}
|
||||
virtual QString Name() const override {return "RD";}
|
||||
};
|
||||
|
||||
class RDA : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(5);}
|
||||
virtual QString Name() const override {return "RDA";}
|
||||
};
|
||||
|
||||
class WR : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(6);}
|
||||
virtual QString Name() const override {return "WR";}
|
||||
};
|
||||
|
||||
class WRA : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(7);}
|
||||
virtual QString Name() const override {return "WRA";}
|
||||
};
|
||||
|
||||
class AUTO_REFRESH : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const override {return "REF";}
|
||||
virtual std::vector<traceTime> getTimesOnCommandBus() const {return {span.Begin()};}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {QColor phaseColor = QColor(Qt::darkCyan);
|
||||
phaseColor.setAlpha(130);
|
||||
return phaseColor;
|
||||
}
|
||||
};
|
||||
|
||||
class PRECHARGE_ALL : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const override {return "PREA";}
|
||||
virtual std::vector<traceTime> getTimesOnCommandBus() const {return {span.Begin()};}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return ColorGenerator::getColor(10);}
|
||||
};
|
||||
|
||||
class PDNA : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const override {return "PDNA";}
|
||||
virtual Qt::BrushStyle getBrushStyle() const override {return Qt::Dense6Pattern;}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return QColor(Qt::black);}
|
||||
virtual Phase::PhaseSymbol getPhaseSymbol() const override {return PhaseSymbol::Rect;}
|
||||
};
|
||||
|
||||
class PDNP : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const override {return "PDNP";}
|
||||
virtual Qt::BrushStyle getBrushStyle() const override{return Qt::Dense4Pattern;}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return QColor(Qt::black);}
|
||||
virtual Phase::PhaseSymbol getPhaseSymbol() const override {return PhaseSymbol::Rect;}
|
||||
};
|
||||
|
||||
class SREF : public Phase
|
||||
{
|
||||
public:
|
||||
using Phase::Phase;
|
||||
protected:
|
||||
virtual QString Name() const final {return "SREF";}
|
||||
virtual Qt::BrushStyle getBrushStyle() const {return Qt::Dense1Pattern;}
|
||||
virtual QColor getColor(const TraceDrawingProperties &drawingProperties) const override {Q_UNUSED(drawingProperties) return getPhaseColor();}
|
||||
virtual QColor getPhaseColor() const override {return QColor(Qt::black);}
|
||||
virtual Phase::PhaseSymbol getPhaseSymbol() const override {return PhaseSymbol::Rect;}
|
||||
};
|
||||
|
||||
#endif // BANKPHASE_H
|
||||
45
analyzer/analyzer/businessObjects/phases/phasefactory.cpp
Normal file
45
analyzer/analyzer/businessObjects/phases/phasefactory.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "phasefactory.h"
|
||||
#include <exception>
|
||||
#include "phase.h"
|
||||
#include "businessObjects/transaction.h"
|
||||
#include "data/tracedb.h"
|
||||
#include "businessObjects/timespan.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
shared_ptr<Phase> PhaseFactory::CreatePhase(ID id, const QString& dbPhaseName,const Timespan& span, const shared_ptr<Transaction>& trans, TraceDB& database)
|
||||
{
|
||||
traceTime clk = database.getGeneralInfo().clkPeriod;
|
||||
|
||||
if(dbPhaseName == "REQ")
|
||||
return shared_ptr<Phase>(new REQ(id, span,trans,{},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "RESP")
|
||||
return shared_ptr<Phase>(new RESP(id, span,trans,{},std::shared_ptr<Timespan>()));
|
||||
|
||||
else if(dbPhaseName == "PRE")
|
||||
return shared_ptr<Phase>(new PRE(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "ACT")
|
||||
return shared_ptr<Phase>(new ACT(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "PRE_ALL")
|
||||
return shared_ptr<Phase>(new PRECHARGE_ALL(id,span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "AUTO_REFRESH")
|
||||
return shared_ptr<Phase>(new AUTO_REFRESH(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>()));
|
||||
|
||||
else if(dbPhaseName == "RD")
|
||||
return shared_ptr<Phase>(new RD(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>(new Timespan(trans->SpanOnDataStrobe()))));
|
||||
else if(dbPhaseName == "RDA")
|
||||
return shared_ptr<Phase>(new RDA(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>(new Timespan(trans->SpanOnDataStrobe()))));
|
||||
else if(dbPhaseName == "WR")
|
||||
return shared_ptr<Phase>(new WR(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>(new Timespan(trans->SpanOnDataStrobe()))));
|
||||
else if(dbPhaseName == "WRA")
|
||||
return shared_ptr<Phase>(new WRA(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr<Timespan>(new Timespan(trans->SpanOnDataStrobe()))));
|
||||
|
||||
else if(dbPhaseName == "SREF")
|
||||
return shared_ptr<Phase>(new SREF(id, span, trans,{Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "PDNA")
|
||||
return shared_ptr<Phase>(new PDNA(id, span,trans, {Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr<Timespan>()));
|
||||
else if(dbPhaseName == "PDNP")
|
||||
return shared_ptr<Phase>(new PDNP(id, span,trans, {Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr<Timespan>()));
|
||||
else
|
||||
throw std::runtime_error("DB phasename " + dbPhaseName.toStdString() + " unkown to phasefactory");
|
||||
}
|
||||
18
analyzer/analyzer/businessObjects/phases/phasefactory.h
Normal file
18
analyzer/analyzer/businessObjects/phases/phasefactory.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef PHASEFACTORY_H
|
||||
#define PHASEFACTORY_H
|
||||
#include "phase.h"
|
||||
#include <QStringList>
|
||||
#include <memory>
|
||||
#include "businessObjects/transaction.h"
|
||||
|
||||
class TraceDB;
|
||||
|
||||
class PhaseFactory
|
||||
{
|
||||
private:
|
||||
PhaseFactory();
|
||||
public:
|
||||
static std::shared_ptr<Phase> CreatePhase(ID id, const QString& dbPhaseName,const Timespan& span,const std::shared_ptr<Transaction>& trans, TraceDB& database);
|
||||
};
|
||||
|
||||
#endif // PHASEFACTORY_H
|
||||
108
analyzer/analyzer/businessObjects/pythoncaller.cpp
Normal file
108
analyzer/analyzer/businessObjects/pythoncaller.cpp
Normal file
@@ -0,0 +1,108 @@
|
||||
#include "pythoncaller.h"
|
||||
#include <exception>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <QFileInfo>
|
||||
#include <QDebug>
|
||||
|
||||
using namespace std;
|
||||
|
||||
PythonCaller::PythonCaller(const QString& pathToScripts) :
|
||||
testModuleName("tests"), testFunctionName("runTests"), metricModuleName("metrics"), metricFunctionName("calculateMetrics"), pathToScripts(pathToScripts.toStdString())
|
||||
{
|
||||
Py_Initialize();
|
||||
PyObject *sysPath = PySys_GetObject((char*)"path");
|
||||
PyObject *path = PyUnicode_FromString(this->pathToScripts.c_str());
|
||||
PyList_Insert(sysPath, 0, path);
|
||||
Py_DECREF(path);
|
||||
|
||||
qDebug() << testModuleName.c_str() << testFunctionName.c_str();
|
||||
|
||||
pRunTestsFunction = loadFunctionFromModule(testModuleName, testFunctionName);
|
||||
pCalculateMetricsFunction = loadFunctionFromModule(metricModuleName, metricFunctionName);
|
||||
}
|
||||
|
||||
|
||||
//returns new reference to the function (see: http://edcjones.tripod.com/refcount.html for the difference between "new reference" and "borrowed reference")
|
||||
PyObject* PythonCaller::loadFunctionFromModule(string moduleName,string functionName)
|
||||
{
|
||||
PyObject* pModuleName = PyUnicode_FromString(moduleName.c_str());
|
||||
PyObject* pModule = PyImport_Import(pModuleName);
|
||||
|
||||
if(!pModule)
|
||||
{
|
||||
throw runtime_error(string("Could not load module "+ moduleName));
|
||||
}
|
||||
|
||||
PyObject* pFunction = PyObject_GetAttrString(pModule, functionName.c_str());
|
||||
|
||||
if(!pFunction || !PyCallable_Check(pFunction))
|
||||
{
|
||||
throw runtime_error(string("Could not load test function " + functionName + "in module " + moduleName));
|
||||
}
|
||||
|
||||
Py_DECREF(pModuleName);
|
||||
Py_DECREF(pModule);
|
||||
return pFunction;
|
||||
}
|
||||
|
||||
PythonCaller::~PythonCaller()
|
||||
{
|
||||
Py_DECREF(pRunTestsFunction);
|
||||
Py_DECREF(pCalculateMetricsFunction);
|
||||
Py_Finalize();
|
||||
}
|
||||
|
||||
//returns a new reference to result of function call
|
||||
PyObject* PythonCaller::callFunctionWithStringArgument(PyObject* function, QString argument)
|
||||
{
|
||||
assert(PyCallable_Check(function));
|
||||
|
||||
PyObject* pArgs = PyTuple_New(1);
|
||||
PyObject* pArgument = PyUnicode_FromString(argument.toStdString().c_str());
|
||||
PyTuple_SetItem(pArgs, 0, pArgument);
|
||||
PyObject *pResult = PyObject_CallObject(function, pArgs);
|
||||
Py_DECREF(pArgument);
|
||||
|
||||
if(!pResult)
|
||||
{
|
||||
PyErr_Print();
|
||||
throw runtime_error(string("Error in calling " + testFunctionName + "in module " + testModuleName));
|
||||
}
|
||||
|
||||
return pResult;
|
||||
}
|
||||
TraceTestResults PythonCaller::runTestsOnTrace(QString pathToTrace)
|
||||
{
|
||||
TraceTestResults traceTestResult(QFileInfo(pathToTrace).baseName());
|
||||
PyObject *pResult = callFunctionWithStringArgument(pRunTestsFunction, pathToTrace);
|
||||
|
||||
for(Py_ssize_t i= 0; i < PyList_Size(pResult); ++i)
|
||||
{
|
||||
PyObject* currentTestResult = PyList_GetItem(pResult,i);
|
||||
QString testName(PyUnicode_AsUTF8(PyTuple_GetItem(currentTestResult,0)));
|
||||
bool testPassed = (Py_True == PyTuple_GetItem(currentTestResult,1));
|
||||
QString message(PyUnicode_AsUTF8(PyTuple_GetItem(currentTestResult,2)));
|
||||
|
||||
traceTestResult.addTestResult(TestResult(testName,testPassed,message));
|
||||
}
|
||||
Py_DECREF(pResult);
|
||||
return traceTestResult;
|
||||
}
|
||||
|
||||
TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace)
|
||||
{
|
||||
TraceCalculatedMetrics result(QFileInfo(pathToTrace).baseName());
|
||||
PyObject *pResult = callFunctionWithStringArgument(pCalculateMetricsFunction, pathToTrace);
|
||||
|
||||
for(Py_ssize_t i= 0; i < PyList_Size(pResult); ++i)
|
||||
{
|
||||
PyObject* calculatedMetric = PyList_GetItem(pResult,i);
|
||||
QString metricName(PyUnicode_AsUTF8(PyTuple_GetItem(calculatedMetric,0)));
|
||||
double value = PyFloat_AsDouble(PyTuple_GetItem(calculatedMetric,1));
|
||||
result.addCalculatedMetric(CalculatedMetric(metricName,value));
|
||||
}
|
||||
|
||||
Py_DECREF(pResult);
|
||||
return result;
|
||||
}
|
||||
26
analyzer/analyzer/businessObjects/pythoncaller.h
Normal file
26
analyzer/analyzer/businessObjects/pythoncaller.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef PYTHONCALLER_H
|
||||
#define PYTHONCALLER_H
|
||||
#include <Python.h>
|
||||
#include <QString>
|
||||
#include <string>
|
||||
#include "businessObjects/tracetestresults.h"
|
||||
#include "businessObjects/tracecalculatedmetrics.h"
|
||||
|
||||
class PythonCaller
|
||||
{
|
||||
public:
|
||||
PythonCaller(const QString& pathToScripts);
|
||||
~PythonCaller();
|
||||
TraceTestResults runTestsOnTrace(QString pathToTrace);
|
||||
TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace);
|
||||
|
||||
private:
|
||||
PyObject *pRunTestsFunction, *pCalculateMetricsFunction;
|
||||
PyObject* loadFunctionFromModule(std::string moduleName, std::string functionName);
|
||||
std::string testModuleName, testFunctionName, metricModuleName, metricFunctionName, pathToScripts;
|
||||
PyObject *callFunctionWithStringArgument(PyObject *function, QString argument);
|
||||
};
|
||||
|
||||
#endif // PYTHONCALLER_H
|
||||
|
||||
|
||||
22
analyzer/analyzer/businessObjects/testresult.h
Normal file
22
analyzer/analyzer/businessObjects/testresult.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef TESTRESULT_H
|
||||
#define TESTRESULT_H
|
||||
#include <QString>
|
||||
|
||||
class TestResult
|
||||
{
|
||||
public:
|
||||
TestResult(const QString& testName, bool passed, QString& message) :
|
||||
testName(testName),passed(passed),message(message){}
|
||||
|
||||
QString getTestName() const{return testName;}
|
||||
QString getMessage() const{return message;}
|
||||
bool hasPassed() const{return passed;}
|
||||
|
||||
private:
|
||||
QString testName;
|
||||
bool passed;
|
||||
QString message;
|
||||
|
||||
};
|
||||
|
||||
#endif // TESTRESULT_H
|
||||
12
analyzer/analyzer/businessObjects/timespan.cpp
Normal file
12
analyzer/analyzer/businessObjects/timespan.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "timespan.h"
|
||||
|
||||
bool Timespan::contains(traceTime time) const
|
||||
{
|
||||
return (begin<=time && time<=end);
|
||||
}
|
||||
|
||||
void Timespan::shift(traceTime offset)
|
||||
{
|
||||
begin += offset;
|
||||
end += offset;
|
||||
}
|
||||
24
analyzer/analyzer/businessObjects/timespan.h
Normal file
24
analyzer/analyzer/businessObjects/timespan.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef TIMESPAN_H
|
||||
#define TIMESPAN_H
|
||||
#include <QString>
|
||||
#include "tracetime.h"
|
||||
#include "thirdParty/eng_format.h"
|
||||
|
||||
class Timespan
|
||||
{
|
||||
traceTime begin;
|
||||
traceTime end;
|
||||
public:
|
||||
|
||||
Timespan(traceTime begin = 0, traceTime end = 0) : begin(begin), end(end){}
|
||||
traceTime timeCovered() const{return abs(End()-Begin());}
|
||||
traceTime Begin() const{return begin;}
|
||||
void setBegin(traceTime time){begin = time;}
|
||||
traceTime End() const{return end;}
|
||||
traceTime Middle() const{return (begin + end) / 2;}
|
||||
void setEnd(traceTime time){end = time;}
|
||||
bool contains(traceTime time) const;
|
||||
void shift(traceTime offset);
|
||||
};
|
||||
|
||||
#endif // TIMESPAN_H
|
||||
46
analyzer/analyzer/businessObjects/tracecalculatedmetrics.h
Normal file
46
analyzer/analyzer/businessObjects/tracecalculatedmetrics.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef TRACEMETRICRESULTS_H
|
||||
#define TRACEMETRICRESULTS_H
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "calculatedMetric.h"
|
||||
|
||||
class TraceCalculatedMetrics
|
||||
{
|
||||
public:
|
||||
TraceCalculatedMetrics(const QString& traceName): traceName(traceName){}
|
||||
|
||||
void addCalculatedMetric(const CalculatedMetric& result) {calculatedMetrics.push_back(result);}
|
||||
QString getTraceName() const {return traceName;}
|
||||
const std::vector<CalculatedMetric>& getCalculatedMetrics() const{return calculatedMetrics;}
|
||||
|
||||
QString toCSVHeader()
|
||||
{
|
||||
QString result = "";
|
||||
result.append("Trace");
|
||||
for(CalculatedMetric calculatedMetric : calculatedMetrics)
|
||||
{
|
||||
result.append(",");
|
||||
result.append(calculatedMetric.getName());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
QString toCSVLine()
|
||||
{
|
||||
QString result = "";
|
||||
result.append(traceName);
|
||||
for(CalculatedMetric calculatedMetric : calculatedMetrics)
|
||||
{
|
||||
result.append(",");
|
||||
result.append(QString::number(calculatedMetric.getValue()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
QString traceName;
|
||||
std::vector<CalculatedMetric> calculatedMetrics;
|
||||
};
|
||||
|
||||
|
||||
#endif // TRACEMETRICRESULTS_H
|
||||
12
analyzer/analyzer/businessObjects/tracetestresults.cpp
Normal file
12
analyzer/analyzer/businessObjects/tracetestresults.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "tracetestresults.h"
|
||||
|
||||
|
||||
bool TraceTestResults::hasPassedAllTests() const
|
||||
{
|
||||
for(const TestResult& testResult: testResults)
|
||||
{
|
||||
if(!testResult.hasPassed())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
22
analyzer/analyzer/businessObjects/tracetestresults.h
Normal file
22
analyzer/analyzer/businessObjects/tracetestresults.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef TRACETESTRESULT_H
|
||||
#define TRACETESTRESULT_H
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "testresult.h"
|
||||
|
||||
class TraceTestResults
|
||||
{
|
||||
public:
|
||||
TraceTestResults(const QString& traceName): traceName(traceName){}
|
||||
|
||||
void addTestResult(const TestResult& result) {testResults.push_back(result);}
|
||||
|
||||
QString getTraceName() const {return traceName;}
|
||||
bool hasPassedAllTests() const;
|
||||
const std::vector<TestResult>& getTestResults() const{return testResults;}
|
||||
private:
|
||||
QString traceName;
|
||||
std::vector<TestResult> testResults;
|
||||
};
|
||||
|
||||
#endif // TRACETESTRESULT_H
|
||||
27
analyzer/analyzer/businessObjects/tracetime.h
Normal file
27
analyzer/analyzer/businessObjects/tracetime.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef TRACETIME_H
|
||||
#define TRACETIME_H
|
||||
#include <QString>
|
||||
#include "thirdParty/eng_format.h"
|
||||
|
||||
//time in nanoseconds
|
||||
typedef long long traceTime;
|
||||
|
||||
inline QString prettyFormatTime(traceTime time)
|
||||
{
|
||||
return QString::number(time/1000) + QString(" ns");
|
||||
}
|
||||
|
||||
inline QString formatInClks(traceTime time, unsigned int clkPeriod)
|
||||
{
|
||||
long long numberOfClockCovered = time/clkPeriod;
|
||||
QString suffix = (numberOfClockCovered != 1) ? QString(" clks") : QString(" clk");
|
||||
return QString::number(numberOfClockCovered) + suffix;
|
||||
}
|
||||
|
||||
inline traceTime alignToClk(traceTime time, unsigned int clkPeriod)
|
||||
{
|
||||
return round(1.0*time/clkPeriod)*clkPeriod;
|
||||
}
|
||||
|
||||
|
||||
#endif // TRACETIME_H
|
||||
30
analyzer/analyzer/businessObjects/transaction.cpp
Normal file
30
analyzer/analyzer/businessObjects/transaction.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "transaction.h"
|
||||
|
||||
using namespace std;
|
||||
Transaction::Transaction(ID id,unsigned int address,unsigned int burstlength,int thread, unsigned int channel, unsigned int bank,unsigned int bankgroup, unsigned int row, unsigned int column, Timespan span, Timespan spanOnDataStrobe)
|
||||
:address(address),burstlength(burstlength),channel(channel), bank(bank),bankgroup(bankgroup), row(row), column(column),thread(thread),span(span),spanOnDataStrobe(spanOnDataStrobe),id(id){}
|
||||
|
||||
void Transaction::addPhase(shared_ptr<Phase> phase)
|
||||
{
|
||||
phases.push_back(phase);
|
||||
}
|
||||
|
||||
void Transaction::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, bool highlight, const TraceDrawingProperties &drawingProperties) const
|
||||
{
|
||||
for(shared_ptr<Phase> phase: phases)
|
||||
phase->draw(painter,xMap,yMap,canvasRect,highlight,drawingProperties);
|
||||
}
|
||||
|
||||
bool Transaction::isSelected(traceTime time, double yVal, const TraceDrawingProperties& drawingproperties) const
|
||||
{
|
||||
if(span.contains(time))
|
||||
{
|
||||
for(shared_ptr<Phase> phase: phases)
|
||||
{
|
||||
if(phase->isSelected(time,yVal,drawingproperties))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
45
analyzer/analyzer/businessObjects/transaction.h
Normal file
45
analyzer/analyzer/businessObjects/transaction.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef TRANSACTION_H
|
||||
#define TRANSACTION_H
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "timespan.h"
|
||||
#include "phases/phase.h"
|
||||
#include "presentation/tracedrawingproperties.h"
|
||||
|
||||
typedef unsigned int ID;
|
||||
|
||||
class Transaction
|
||||
{
|
||||
private:
|
||||
unsigned int address,burstlength,channel,bank,bankgroup,row,column;
|
||||
int thread;
|
||||
Timespan span;
|
||||
Timespan spanOnDataStrobe;
|
||||
ID id;
|
||||
std::vector<std::shared_ptr<Phase>> phases;
|
||||
|
||||
public:
|
||||
Transaction(ID id,unsigned int address,unsigned int burstlength,int thread, unsigned int channel, unsigned int bank,unsigned int bankgroup, unsigned int row, unsigned int column, Timespan span, Timespan spanOnDataStrobe);
|
||||
|
||||
void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect, bool highlight,const TraceDrawingProperties& drawingProperties) const;
|
||||
void addPhase(std::shared_ptr<Phase> phase);
|
||||
|
||||
bool isSelected(traceTime time,double yVal, const TraceDrawingProperties& drawingproperties) const;
|
||||
bool isControllerInternal(){return thread==0;}
|
||||
|
||||
unsigned int Address() const{return address;}
|
||||
unsigned int Burstlength() const{return burstlength;}
|
||||
int Thread() {return thread;}
|
||||
unsigned int Channel() const {return channel;}
|
||||
unsigned int Bank() const{return bank;}
|
||||
unsigned int BankGroup() const{return bankgroup;}
|
||||
unsigned int Row() const{return row;}
|
||||
unsigned int Column() const{return column;}
|
||||
ID Id() const {return id;}
|
||||
const Timespan& Span() const{return span;}
|
||||
const Timespan& SpanOnDataStrobe() {return spanOnDataStrobe;}
|
||||
const std::vector<std::shared_ptr<Phase>>& Phases() const{return phases;}
|
||||
|
||||
};
|
||||
|
||||
#endif // TRANSACTION_H
|
||||
22
analyzer/analyzer/data/QueryTexts.h
Normal file
22
analyzer/analyzer/data/QueryTexts.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef QUERYTEXTS_H
|
||||
#define QUERYTEXTS_H
|
||||
#include <QString>
|
||||
|
||||
struct TransactionQueryTexts
|
||||
{
|
||||
QString queryHead;
|
||||
QString selectTransactionsByTimespan,selectTransactionById;
|
||||
|
||||
TransactionQueryTexts()
|
||||
{
|
||||
queryHead = "SELECT Transactions.ID AS TransactionID, Ranges.begin, Ranges.end,DataStrobeBegin,DataStrobeEnd, Address,Burstlength, TThread, TChannel, TBank,TBankgroup, TRow, TColumn,Phases.ID AS PhaseID, PhaseName, PhaseBegin, PhaseEnd "
|
||||
" FROM Transactions INNER JOIN Phases ON Phases.Transact = Transactions.ID INNER JOIN Ranges ON Transactions.Range = Ranges.ID ";
|
||||
|
||||
selectTransactionsByTimespan = queryHead + " WHERE Ranges.end >= :begin AND Ranges.begin <= :end";
|
||||
selectTransactionById = queryHead + " WHERE Transactions.ID = :id";
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif // QUERYTEXTS_H
|
||||
349
analyzer/analyzer/data/tracedb.cpp
Normal file
349
analyzer/analyzer/data/tracedb.cpp
Normal file
@@ -0,0 +1,349 @@
|
||||
#include<QString>
|
||||
#include<QFile>
|
||||
#include<QStringList>
|
||||
#include<QTextStream>
|
||||
#include<QSqlError>
|
||||
#include<iostream>
|
||||
#include <QFileInfo>
|
||||
#include"data/tracedb.h"
|
||||
#include"businessObjects/comment.h"
|
||||
#include "businessObjects/phases/phasefactory.h"
|
||||
|
||||
|
||||
//define symbol printqueries if all queries should be printed to the console
|
||||
#define printqueries
|
||||
|
||||
using namespace std;
|
||||
|
||||
TraceDB::TraceDB(QString path,bool openExisting)
|
||||
{
|
||||
this->pathToDB = path;
|
||||
database = QSqlDatabase::addDatabase("QSQLITE",path);
|
||||
database.setDatabaseName(path);
|
||||
database.open();
|
||||
if(!openExisting)
|
||||
dropAndCreateTables();
|
||||
prepareQueries();
|
||||
generalInfo = getGeneralInfoFromDB();
|
||||
}
|
||||
|
||||
void TraceDB::prepareQueries()
|
||||
{
|
||||
selectTransactionsByTimespan = QSqlQuery(database);
|
||||
selectTransactionsByTimespan.prepare(queryTexts.selectTransactionsByTimespan);
|
||||
selectTransactionById = QSqlQuery(database);
|
||||
|
||||
selectTransactionById.prepare(queryTexts.selectTransactionById);
|
||||
selectDebugMessagesByTimespan = QSqlQuery(database);
|
||||
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");
|
||||
}
|
||||
|
||||
void TraceDB::updateComments(vector<Comment> comments)
|
||||
{
|
||||
|
||||
QSqlQuery query(database);
|
||||
query.prepare("DELETE FROM Comments");
|
||||
executeQuery(query);
|
||||
query.prepare("insert into Comments values(:time,:text)");
|
||||
|
||||
for(const Comment &comment:comments)
|
||||
{
|
||||
query.bindValue(":time",comment.Time());
|
||||
query.bindValue(":text",comment.Text());
|
||||
executeQuery(query);
|
||||
}
|
||||
}
|
||||
|
||||
void TraceDB::updateFileDescription(const QString &description)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("UPDATE GeneralInfo SET Description=:description");
|
||||
query.bindValue(":description",description);
|
||||
executeQuery(query);
|
||||
}
|
||||
|
||||
void TraceDB::refreshData()
|
||||
{
|
||||
generalInfo = getGeneralInfoFromDB();
|
||||
}
|
||||
|
||||
//QueryText must select the fields
|
||||
//TransactionID, Ranges.begin, Ranges.end, Address, TThread, TChannel, TBank, TRow, TColumn, Phases.ID AS PhaseID, PhaseName, PhaseBegin, PhaseEnd
|
||||
vector<shared_ptr<Transaction>> TraceDB::getTransactionsWithCustomQuery(QString queryText)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare(queryText);
|
||||
executeQuery(query);
|
||||
return parseTransactionsFromQuery(query);
|
||||
}
|
||||
|
||||
vector<shared_ptr<Transaction>> TraceDB::getTransactionsInTimespan(const Timespan &span)
|
||||
{
|
||||
selectTransactionsByTimespan.bindValue(":begin",span.Begin());
|
||||
selectTransactionsByTimespan.bindValue(":end",span.End());
|
||||
executeQuery(selectTransactionsByTimespan);
|
||||
return parseTransactionsFromQuery(selectTransactionsByTimespan);
|
||||
}
|
||||
|
||||
|
||||
//TODO Remove exception
|
||||
shared_ptr<Transaction> TraceDB::getTransactionByID(ID id)
|
||||
{
|
||||
selectTransactionById.bindValue(":id", id);
|
||||
executeQuery(selectTransactionById);
|
||||
auto result = parseTransactionsFromQuery(selectTransactionById);
|
||||
if(!result.empty())
|
||||
return result[0];
|
||||
else
|
||||
throw sqlException(("Transaction with ID " + QString::number(id) + " not in DB").toStdString(),this->pathToDB.toStdString());
|
||||
}
|
||||
|
||||
|
||||
shared_ptr<Transaction> TraceDB::getNextActivate(ID currentTransactionId)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead + "WHERE TransactionID > :currentID AND PhaseName = 'ACT' LIMIT 1";
|
||||
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":currentID", currentTransactionId);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
shared_ptr<Transaction> TraceDB::getNextPrecharge(ID currentTransactionId)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead + "WHERE TransactionID > :currentID AND PhaseName IN ('PRE','PRE_ALL') LIMIT 1";
|
||||
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":currentID", currentTransactionId);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
shared_ptr<Transaction> TraceDB::getNextRefresh(ID currentTransactionId)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QString queryText = queryTexts.queryHead + "WHERE TransactionID > :currentID AND PhaseName = 'AUTO_REFRESH' LIMIT 1";
|
||||
|
||||
query.prepare(queryText);
|
||||
query.bindValue(":currentID", currentTransactionId);
|
||||
executeQuery(query);
|
||||
return parseTransactionFromQuery(query);
|
||||
}
|
||||
|
||||
ID TraceDB::getTransactionIDFromPhaseID(ID phaseID)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT Transact FROM Phases WHERE ID=:id");
|
||||
query.bindValue(":id",phaseID);
|
||||
executeQuery(query);
|
||||
|
||||
if(query.next())
|
||||
{
|
||||
return query.value(0).toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw sqlException("Phase with ID "+ to_string(phaseID) + " not in db", this->pathToDB.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
GeneralInfo TraceDB::getGeneralInfoFromDB()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT NumberOfTransactions,TraceEnd,NumberOfBanks,Clk,UnitOfTime,Traces,Memspec,Memconfig FROM GeneralInfo");
|
||||
executeQuery(query);
|
||||
|
||||
if(query.next())
|
||||
{
|
||||
unsigned int numberOfTransactions = query.value(0).toInt();
|
||||
traceTime traceEnd = query.value(1).toLongLong();
|
||||
unsigned int numberOfBanks = query.value(2).toInt();
|
||||
unsigned int clkPeriod = query.value(3).toInt();
|
||||
QString unitOfTime = query.value(4).toString();
|
||||
unsigned int numberOfPhases = getNumberOfPhases();
|
||||
|
||||
QString traces = "Traces: " + query.value(5).toString();
|
||||
QString memspec = "Memspec: " + query.value(6).toString();
|
||||
QString memconfig = "Memconfig: " + query.value(7).toString();
|
||||
|
||||
QString description = (traces + "\n");
|
||||
description += memconfig + "\n";
|
||||
description += memspec + "\n";
|
||||
description += "Number of Transactions: " + QString::number(numberOfTransactions) + "\n";
|
||||
description += "Clock period: " + QString::number(clkPeriod) + " " + unitOfTime + "\n";
|
||||
description += "Length of trace: " + prettyFormatTime(traceEnd);
|
||||
|
||||
return GeneralInfo(numberOfTransactions, numberOfPhases, Timespan(0,traceEnd),numberOfBanks,description,unitOfTime,clkPeriod);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw sqlException("Tracefile corrupted. No general info table", this->pathToDB.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int TraceDB::getNumberOfPhases()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT COUNT(ID) FROM Phases");
|
||||
executeQuery(query);
|
||||
|
||||
query.next();
|
||||
return query.value(0).toInt();
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::getComments()
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
query.prepare("SELECT Time,Text From Comments");
|
||||
executeQuery(query);
|
||||
return parseCommentsFromQuery(query);
|
||||
}
|
||||
|
||||
|
||||
vector<Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span)
|
||||
{
|
||||
selectDebugMessagesByTimespan.bindValue(":begin",span.Begin());
|
||||
selectDebugMessagesByTimespan.bindValue(":end",span.End());
|
||||
executeQuery(selectDebugMessagesByTimespan);
|
||||
|
||||
return parseCommentsFromQuery(selectDebugMessagesByTimespan);
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::getDebugMessagesInTimespan(const Timespan &span, unsigned int limit = 50)
|
||||
{
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":begin",span.Begin());
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":end",span.End());
|
||||
selectDebugMessagesByTimespanWithLimit.bindValue(":limit",limit);
|
||||
executeQuery(selectDebugMessagesByTimespanWithLimit);
|
||||
return parseCommentsFromQuery(selectDebugMessagesByTimespanWithLimit);
|
||||
}
|
||||
|
||||
/* Helpers
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
shared_ptr<Transaction> TraceDB::parseTransactionFromQuery(QSqlQuery &query)
|
||||
{
|
||||
auto result = parseTransactionsFromQuery(query);
|
||||
if(!result.empty())
|
||||
return result[0];
|
||||
else
|
||||
return shared_ptr<Transaction>();
|
||||
}
|
||||
|
||||
vector<shared_ptr<Transaction>> TraceDB::parseTransactionsFromQuery(QSqlQuery &query)
|
||||
{
|
||||
vector<shared_ptr<Transaction>> result;
|
||||
|
||||
bool firstIteration = true;
|
||||
ID currentID = 0;
|
||||
int i = -1;
|
||||
|
||||
while(query.next()){
|
||||
|
||||
ID id = query.value(0).toInt();
|
||||
|
||||
if(currentID != id || firstIteration)
|
||||
{
|
||||
++i;
|
||||
firstIteration = false;
|
||||
currentID = id;
|
||||
Timespan span(query.value(1).toLongLong(),query.value(2).toLongLong());
|
||||
Timespan spanOnStrobe(query.value(3).toLongLong(),query.value(4).toLongLong());
|
||||
unsigned int address = query.value(5).toInt();
|
||||
unsigned int burstlength = query.value(6).toInt();
|
||||
int thread= query.value(7).toInt();
|
||||
unsigned int channel = query.value(8).toInt();
|
||||
unsigned int bank = query.value(9).toInt();
|
||||
unsigned int bankgroup = query.value(10).toInt();
|
||||
unsigned int row = query.value(11).toInt();
|
||||
unsigned int column = query.value(12).toInt();
|
||||
result.push_back(shared_ptr<Transaction>(new Transaction(id,address,burstlength,thread,channel,bank,bankgroup,row,column,span,spanOnStrobe)));
|
||||
}
|
||||
|
||||
unsigned int phaseID = query.value(13).toInt();
|
||||
QString phaseName = query.value(14).toString();
|
||||
Timespan span(query.value(15).toLongLong(),query.value(16).toLongLong());
|
||||
result.at(result.size()-1)->addPhase(PhaseFactory::CreatePhase(phaseID,phaseName,span,result.at(result.size()-1),*this));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
vector<Comment> TraceDB::parseCommentsFromQuery(QSqlQuery &query)
|
||||
{
|
||||
vector<Comment> result;
|
||||
while(query.next())
|
||||
{
|
||||
result.push_back(Comment(query.value(0).toLongLong(),query.value(1).toString()));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void TraceDB::executeQuery(QSqlQuery query)
|
||||
{
|
||||
|
||||
//query.exec returns bool indicating if the query was sucessfull
|
||||
if(query.exec())
|
||||
{
|
||||
#ifdef printqueries
|
||||
cout << queryToString(query).toStdString() << endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw sqlException( ("Query:\n " + queryToString(query) + "\n failed. Error: \n"+
|
||||
query.lastError().text()).toStdString(), this->pathToDB.toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
QString TraceDB::queryToString(QSqlQuery query)
|
||||
{
|
||||
QString str = query.lastQuery();
|
||||
QMapIterator<QString, QVariant> it(query.boundValues());
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
str.replace(it.key(),it.value().toString());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
void TraceDB::dropAndCreateTables()
|
||||
{
|
||||
executeScriptFile("common/static/createTraceDB.sql");
|
||||
}
|
||||
|
||||
void TraceDB::executeScriptFile(QString fileName)
|
||||
{
|
||||
QSqlQuery query(database);
|
||||
QFile scriptFile(fileName);
|
||||
|
||||
if (scriptFile.open(QIODevice::ReadOnly))
|
||||
{
|
||||
// The SQLite driver executes only a single (the first) query in the QSqlQuery
|
||||
// if the script contains more queries, it needs to be splitted.
|
||||
QStringList scriptQueries = QTextStream(&scriptFile).readAll().split(';');
|
||||
|
||||
for (QString &queryTxt : scriptQueries)
|
||||
{
|
||||
if (queryTxt.trimmed().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (!query.exec(queryTxt))
|
||||
{
|
||||
throw sqlException("Querry failed:" + query.lastError().text().toStdString(), this->pathToDB.toStdString());
|
||||
}
|
||||
query.finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
96
analyzer/analyzer/data/tracedb.h
Normal file
96
analyzer/analyzer/data/tracedb.h
Normal file
@@ -0,0 +1,96 @@
|
||||
#ifndef TRACEDB_H
|
||||
#define TRACEDB_H
|
||||
|
||||
#include<string>
|
||||
#include<exception>
|
||||
#include<QString>
|
||||
#include<QSqlDatabase>
|
||||
#include<QSqlQuery>
|
||||
#include<QSqlTableModel>
|
||||
#include<vector>
|
||||
#include <string>
|
||||
#include "businessObjects/transaction.h"
|
||||
#include "businessObjects/generalinfo.h"
|
||||
#include "businessObjects/phases/phasefactory.h"
|
||||
#include "businessObjects/comment.h"
|
||||
#include "QueryTexts.h"
|
||||
|
||||
/* TraceDB handles the connection to a SQLLite database containing trace data.
|
||||
* A TraceDB object always holds an open connection to a valid database.
|
||||
*/
|
||||
|
||||
class TraceDB : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TraceDB(QString path, bool openExisting);
|
||||
const QString& getPathToDB(){return pathToDB;}
|
||||
|
||||
void updateComments(std::vector<Comment> comments);
|
||||
void updateFileDescription(const QString &description);
|
||||
void refreshData();
|
||||
|
||||
const GeneralInfo& getGeneralInfo() {return generalInfo;}
|
||||
|
||||
std::vector<std::shared_ptr<Transaction>> getTransactionsWithCustomQuery(QString queryText);
|
||||
std::vector<std::shared_ptr<Transaction>> getTransactionsInTimespan(const Timespan &span);
|
||||
std::shared_ptr<Transaction> getNextPrecharge(ID currentTransactionId);
|
||||
std::shared_ptr<Transaction> getNextActivate(ID currentTransactionId);
|
||||
std::shared_ptr<Transaction> getNextRefresh(ID currentTransactionId);
|
||||
|
||||
|
||||
std::shared_ptr<Transaction> getTransactionByID(ID id);
|
||||
ID getTransactionIDFromPhaseID(ID phaseID);
|
||||
|
||||
std::vector<Comment> getComments();
|
||||
std::vector<Comment> getDebugMessagesInTimespan(const Timespan &span);
|
||||
std::vector<Comment> getDebugMessagesInTimespan(const Timespan &span, unsigned int limit);
|
||||
|
||||
private:
|
||||
QString pathToDB;
|
||||
QSqlDatabase database;
|
||||
GeneralInfo generalInfo;
|
||||
|
||||
QSqlQuery insertPhaseQuery;
|
||||
QSqlQuery insertTransactionQuery;
|
||||
QSqlQuery selectTransactionsByTimespan;
|
||||
QSqlQuery selectTransactionById;
|
||||
QSqlQuery selectDebugMessagesByTimespan;
|
||||
QSqlQuery selectDebugMessagesByTimespanWithLimit;
|
||||
|
||||
TransactionQueryTexts queryTexts;
|
||||
void prepareQueries();
|
||||
void executeQuery(QSqlQuery query);
|
||||
QString queryToString(QSqlQuery query);
|
||||
std::shared_ptr<Transaction> parseTransactionFromQuery(QSqlQuery &query);
|
||||
std::vector<std::shared_ptr<Transaction>> parseTransactionsFromQuery(QSqlQuery &query);
|
||||
std::vector<Comment> parseCommentsFromQuery(QSqlQuery &query);
|
||||
|
||||
void executeScriptFile(QString fileName);
|
||||
void dropAndCreateTables();
|
||||
|
||||
unsigned int getNumberOfPhases();
|
||||
GeneralInfo getGeneralInfoFromDB();
|
||||
};
|
||||
|
||||
|
||||
|
||||
class sqlException : public std::exception
|
||||
{
|
||||
private:
|
||||
std::string message;
|
||||
public:
|
||||
sqlException(std::string message, std::string filename)
|
||||
{
|
||||
this->message = std::string("Error in file ") + filename + std::string(" ") + message;
|
||||
}
|
||||
const char* what() const noexcept
|
||||
{
|
||||
return message.c_str();
|
||||
}
|
||||
};
|
||||
#endif // TRACEDB_H
|
||||
|
||||
|
||||
|
||||
172
analyzer/analyzer/evaluationtool.cpp
Normal file
172
analyzer/analyzer/evaluationtool.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
#include <QFileInfo>
|
||||
#include <QtAlgorithms>
|
||||
#include <QPainter>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <businessObjects/tracetestresults.h>
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QFileDialog>
|
||||
#include "evaluationtool.h"
|
||||
#include "ui_evaluationtool.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
EvaluationTool::EvaluationTool(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::EvaluationTool), resourcesRelPath("/../../dram/resources/scripts""")
|
||||
{
|
||||
ui->setupUi(this);
|
||||
traceFilesModel = new QStandardItemModel(this);
|
||||
ui->listView->setModel(traceFilesModel);
|
||||
QObject::connect(ui->traceTestTreeWidget,SIGNAL(setMessage(QString)),this,SLOT(setTestMessage(QString)));
|
||||
}
|
||||
|
||||
EvaluationTool::~EvaluationTool()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EvaluationTool::showForFiles(QList<QString> paths)
|
||||
{
|
||||
cleanUpUI();
|
||||
fillFileList(paths);
|
||||
show();
|
||||
ui->toolBox->setCurrentIndex(0);
|
||||
}
|
||||
|
||||
void EvaluationTool::showAndRunTests(QList<QString> paths)
|
||||
{
|
||||
cleanUpUI();
|
||||
fillFileList(paths);
|
||||
show();
|
||||
ui->toolBox->setCurrentIndex(0);
|
||||
runTests();
|
||||
}
|
||||
|
||||
void EvaluationTool::showAndEvaluateMetrics(QList<QString> paths)
|
||||
{
|
||||
cleanUpUI();
|
||||
fillFileList(paths);
|
||||
show();
|
||||
ui->toolBox->setCurrentIndex(1);
|
||||
calculateMetrics();
|
||||
std::cout<<"done"<<std::endl;
|
||||
}
|
||||
|
||||
void EvaluationTool::cleanUpUI()
|
||||
{
|
||||
traceFilesModel->clear();
|
||||
calculatedMetrics.clear();
|
||||
ui->traceMetricTreeWidget->clear();
|
||||
ui->traceTestTreeWidget->clear();
|
||||
ui->testMessage->setPlainText(QString(""));
|
||||
ui->testLight->setGray();
|
||||
}
|
||||
|
||||
void EvaluationTool::fillFileList(QList<QString> paths)
|
||||
{
|
||||
qSort(paths.begin(), paths.end(), [] (const QString &path1, const QString &path2) {return QFileInfo(path1).baseName() < QFileInfo(path2).baseName();});
|
||||
for(const QString& path: paths)
|
||||
{
|
||||
traceFilesModel->appendRow(new TraceFileItem(path));
|
||||
}
|
||||
}
|
||||
|
||||
void EvaluationTool::on_btn_test_clicked()
|
||||
{
|
||||
runTests();
|
||||
}
|
||||
|
||||
void EvaluationTool::runTests()
|
||||
{
|
||||
QString resourcesAbsPath = QApplication::applicationDirPath() + this->resourcesRelPath;
|
||||
qDebug() << resourcesAbsPath;
|
||||
PythonCaller pythonCaller(this->resourcesRelPath);
|
||||
ui->traceTestTreeWidget->clear();
|
||||
ui->testLight->setGray();
|
||||
|
||||
if(traceFilesModel->rowCount() == 0)
|
||||
return;
|
||||
|
||||
bool allTestsPassed = true;
|
||||
|
||||
for(int row = 0; row < traceFilesModel->rowCount(); ++row)
|
||||
{
|
||||
TraceFileItem* item = static_cast<TraceFileItem*>(traceFilesModel->item(row));
|
||||
TraceTestResults traceTestResult = pythonCaller.runTestsOnTrace(item->getPath());
|
||||
if(!traceTestResult.hasPassedAllTests())
|
||||
allTestsPassed = false;
|
||||
ui->traceTestTreeWidget->addTraceTestResult(traceTestResult);
|
||||
}
|
||||
|
||||
ui->traceTestTreeWidget->expandAll();
|
||||
|
||||
if(allTestsPassed)
|
||||
ui->testLight->setGreen();
|
||||
else
|
||||
ui->testLight->setRed();
|
||||
}
|
||||
|
||||
void EvaluationTool::on_btn_calculateMetrics_clicked()
|
||||
{
|
||||
calculateMetrics();
|
||||
}
|
||||
|
||||
void EvaluationTool::calculateMetrics()
|
||||
{
|
||||
QString resourcesAbsPath = QApplication::applicationDirPath() + this->resourcesRelPath;
|
||||
qDebug() << resourcesAbsPath;
|
||||
PythonCaller pythonCaller(this->resourcesRelPath);
|
||||
ui->traceMetricTreeWidget->clear();
|
||||
for(int row = 0; row < traceFilesModel->rowCount(); ++row)
|
||||
{
|
||||
TraceFileItem* item = static_cast<TraceFileItem*>(traceFilesModel->item(row));
|
||||
TraceCalculatedMetrics result = pythonCaller.calculateMetricsOnTrace(item->getPath());
|
||||
calculatedMetrics.push_back(result);
|
||||
ui->traceMetricTreeWidget->addTraceMetricResults(result);
|
||||
}
|
||||
ui->traceMetricTreeWidget->expandAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EvaluationTool::setTestMessage(QString message)
|
||||
{
|
||||
ui->testMessage->setPlainText(message);
|
||||
}
|
||||
|
||||
EvaluationTool::TraceFileItem::TraceFileItem(const QString &path)
|
||||
{
|
||||
this->path = path;
|
||||
setText(QFileInfo(this->path).baseName());
|
||||
setCheckable( false );
|
||||
setCheckState(Qt::Checked);
|
||||
setEditable(false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void EvaluationTool::on_btn_exportCSV_clicked()
|
||||
{
|
||||
if(calculatedMetrics.size()>0)
|
||||
{
|
||||
QString filename = QFileDialog::getSaveFileName(this, "Export to CSV", "", "Comma separated Values(*.csv)");
|
||||
if(filename != "")
|
||||
{
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
||||
QTextStream out(&file);
|
||||
out << calculatedMetrics[0].toCSVHeader() << "\n";
|
||||
for(TraceCalculatedMetrics& metrics : calculatedMetrics)
|
||||
{
|
||||
out << metrics.toCSVLine() << "\n";
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
62
analyzer/analyzer/evaluationtool.h
Normal file
62
analyzer/analyzer/evaluationtool.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#ifndef EVALUATIONTOOL_H
|
||||
#define EVALUATIONTOOL_H
|
||||
|
||||
#include <Python.h>
|
||||
#include <QWidget>
|
||||
#include <QStandardItem>
|
||||
#include <QStandardItemModel>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <vector>
|
||||
#include "businessObjects/pythoncaller.h"
|
||||
#include "businessObjects/tracecalculatedmetrics.h"
|
||||
|
||||
namespace Ui {
|
||||
class EvaluationTool;
|
||||
}
|
||||
|
||||
class EvaluationTool : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EvaluationTool(QWidget *parent = 0);
|
||||
~EvaluationTool();
|
||||
|
||||
void showForFiles(QList<QString> paths);
|
||||
void showAndRunTests(QList<QString> paths);
|
||||
void showAndEvaluateMetrics(QList<QString> paths);
|
||||
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_btn_test_clicked();
|
||||
void setTestMessage(QString message);
|
||||
void on_btn_calculateMetrics_clicked();
|
||||
|
||||
void on_btn_exportCSV_clicked();
|
||||
|
||||
private:
|
||||
void fillFileList(QList<QString> paths);
|
||||
void runTests();
|
||||
void calculateMetrics();
|
||||
void cleanUpUI();
|
||||
|
||||
|
||||
Ui::EvaluationTool *ui;
|
||||
QStandardItemModel *traceFilesModel;
|
||||
std::vector<TraceCalculatedMetrics> calculatedMetrics;
|
||||
QString resourcesRelPath;
|
||||
|
||||
class TraceFileItem : public QStandardItem
|
||||
{
|
||||
public:
|
||||
TraceFileItem(const QString& path);
|
||||
QString getPath(){return path;}
|
||||
|
||||
private:
|
||||
QString path;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // EVALUATIONTOOL_H
|
||||
188
analyzer/analyzer/evaluationtool.ui
Normal file
188
analyzer/analyzer/evaluationtool.ui
Normal file
@@ -0,0 +1,188 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EvaluationTool</class>
|
||||
<widget class="QWidget" name="EvaluationTool">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>869</width>
|
||||
<height>514</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Evaluate Traces</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>5</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="page">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>432</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Test</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="TraceTestTreeWidget" name="traceTestTreeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_test">
|
||||
<property name="text">
|
||||
<string>Run tests</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="TestLight" name="testLight" native="true">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>30</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Message: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="testMessage"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="page_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>702</width>
|
||||
<height>432</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Calculate Metrics</string>
|
||||
</attribute>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_calculateMetrics">
|
||||
<property name="text">
|
||||
<string>Calculate metrics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btn_exportCSV">
|
||||
<property name="text">
|
||||
<string>Export to CSV</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TraceMetricTreeWidget" name="traceMetricTreeWidget">
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TestLight</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>presentation/util/testlight.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TraceTestTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/tracetesttreewidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TraceMetricTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/tracemetrictreewidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
29
analyzer/analyzer/gototimedialog.cpp
Normal file
29
analyzer/analyzer/gototimedialog.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "gototimedialog.h"
|
||||
#include "ui_gototimedialog.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
GoToTimeDialog::GoToTimeDialog(double* goToSecond,QWidget *parent) :
|
||||
QDialog(parent),
|
||||
goToSecond(goToSecond),
|
||||
ui(new Ui::GoToTimeDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
GoToTimeDialog::~GoToTimeDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void GoToTimeDialog::on_pushButton_clicked()
|
||||
{
|
||||
QLocale c(QLocale::C);
|
||||
bool validNumber;
|
||||
*goToSecond = c.toDouble(ui->timeEdit->text(),&validNumber);
|
||||
if(validNumber)
|
||||
accept();
|
||||
else
|
||||
{
|
||||
QMessageBox::warning(this,"Invalid number","Please enter a valid floating point number");
|
||||
}
|
||||
}
|
||||
30
analyzer/analyzer/gototimedialog.h
Normal file
30
analyzer/analyzer/gototimedialog.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef GOTOTIMEDIALOG_H
|
||||
#define GOTOTIMEDIALOG_H
|
||||
#include <QDialog>
|
||||
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class GoToTimeDialog;
|
||||
}
|
||||
|
||||
class GoToTimeDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GoToTimeDialog(double* goToSecond, QWidget *parent = 0);
|
||||
~GoToTimeDialog();
|
||||
|
||||
|
||||
private:
|
||||
double* goToSecond;
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_pushButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::GoToTimeDialog *ui;
|
||||
};
|
||||
|
||||
#endif // GOTOTIMEDIALOG_H
|
||||
38
analyzer/analyzer/gototimedialog.ui
Normal file
38
analyzer/analyzer/gototimedialog.ui
Normal file
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GoToTimeDialog</class>
|
||||
<widget class="QDialog" name="GoToTimeDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>395</width>
|
||||
<height>45</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Go to time</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="timeEdit"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>ns</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Ok</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
61
analyzer/analyzer/main.cpp
Normal file
61
analyzer/analyzer/main.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
#include "traceanalyzer.h"
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
#include <iostream>
|
||||
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
cout << argv[0] << std::endl;
|
||||
QApplication a(argc, argv);
|
||||
|
||||
if(argc > 1)
|
||||
{
|
||||
QSet<QString> arguments;
|
||||
for(int i = 1;i<argc;++i)
|
||||
arguments.insert(QString(argv[i]));
|
||||
|
||||
StartupOption startupOption = StartupOption::showPlots;
|
||||
QString testflag("-t");
|
||||
if(arguments.contains(testflag))
|
||||
{
|
||||
startupOption = StartupOption::runTests;
|
||||
arguments.remove(testflag);
|
||||
}
|
||||
|
||||
QString openFolderFlag("-f");
|
||||
if(arguments.contains(openFolderFlag))
|
||||
{
|
||||
arguments.remove(openFolderFlag);
|
||||
QStringList nameFilter("*.tdb");
|
||||
QSet<QString> paths = arguments;
|
||||
arguments.clear();
|
||||
for(QString path : paths)
|
||||
{
|
||||
QDir directory(path);
|
||||
QStringList files = directory.entryList(nameFilter);
|
||||
for(QString& file : files)
|
||||
{
|
||||
arguments.insert(path.append("/") + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TraceAnalyzer analyzer(arguments, startupOption);
|
||||
analyzer.show();
|
||||
return a.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
TraceAnalyzer analyzer;
|
||||
analyzer.show();
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
39
analyzer/analyzer/mainwindow.cpp
Normal file
39
analyzer/analyzer/mainwindow.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "traceDB.h"
|
||||
#include "xmldeserializer.h"
|
||||
#include <qwt_plot.h>
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
// xmlDeserializer des("config.xml");
|
||||
// des.xmlToTraceDB("tpr.xml")
|
||||
|
||||
db = new TraceDB("tpr.tdb", true);
|
||||
traceNavigator = new TraceNavigator(db->getGeneralInfo(), this);
|
||||
ui->tracePlot->init(traceNavigator, db);
|
||||
ui->pornoTraceScroller->init(traceNavigator, db, ui->tracePlot);
|
||||
phases = db->getPhasesInTimespan(traceNavigator->GeneralTraceInfo().TraceSpan());
|
||||
transactions = db->getTransactionsInTimespan(traceNavigator->GeneralTraceInfo().TraceSpan());
|
||||
|
||||
ui->qwtPlot->setAxisScale(QwtPlot::xBottom,traceNavigator->GeneralTraceInfo().TraceSpan().Begin(),traceNavigator->GeneralTraceInfo().TraceSpan().End());
|
||||
unsigned int banksize = traceNavigator -> GeneralTraceInfo().NumberOfBanks();
|
||||
ui->qwtPlot->setAxisScale(QwtPlot::yLeft,0.0,banksize + 3, 1.0);
|
||||
|
||||
PhaseCollectionDrawingProperties* drawingProperties = new PhaseCollectionDrawingProperties(banksize,this);
|
||||
drawingProperties->setDrawText(false);
|
||||
drawingProperties->setDrawBorder(false);
|
||||
drawingProperties->setDrawPowerDownStates(false);
|
||||
phaseCollectionPlotItem *phaseCollectionPlot = new phaseCollectionPlotItem(phases,transactions,drawingProperties);
|
||||
phaseCollectionPlot->attach(ui->qwtPlot);
|
||||
|
||||
traceNavigator->navigateToTime(0);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
35
analyzer/analyzer/mainwindow.h
Normal file
35
analyzer/analyzer/mainwindow.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QHash>
|
||||
|
||||
#include "tracenavigator.h"
|
||||
|
||||
class TraceDB;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
//private slots:
|
||||
// void on_horizontalScrollBar_valueChanged(int value);
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
TraceNavigator *traceNavigator;
|
||||
TraceDB *db;
|
||||
QHash<ID,Phase> phases;
|
||||
QHash<ID,Transaction> transactions;
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
13
analyzer/analyzer/markerplotitem.cpp
Normal file
13
analyzer/analyzer/markerplotitem.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "markerplotitem.h"
|
||||
#include "tracedrawing.h"
|
||||
#include <qwt_scale_map.h>
|
||||
|
||||
int MarkerPlotItem::rtti() const
|
||||
{
|
||||
return QwtPlotItem::Rtti_PlotUserItem;
|
||||
}
|
||||
|
||||
void MarkerPlotItem::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const
|
||||
{
|
||||
drawVerticalLine(painter,xMap.transform(time),canvasRect,color,width);
|
||||
}
|
||||
20
analyzer/analyzer/markerplotitem.h
Normal file
20
analyzer/analyzer/markerplotitem.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef MARKERPLOTITEM_H
|
||||
#define MARKERPLOTITEM_H
|
||||
#include <QColor>
|
||||
#include <qwt_plot_item.h>
|
||||
|
||||
class MarkerPlotItem : public QwtPlotItem
|
||||
{
|
||||
private:
|
||||
traceTime time;
|
||||
int width;
|
||||
QColor color;
|
||||
|
||||
public:
|
||||
MarkerPlotItem(traceTime time, int width = 4, QColor color = QColor(Qt::black)):time(time), width(width), color(color){}
|
||||
virtual int rtti() const;
|
||||
virtual void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const;
|
||||
|
||||
};
|
||||
|
||||
#endif // MARKERPLOTITEM_H
|
||||
13
analyzer/analyzer/paths.pro
Normal file
13
analyzer/analyzer/paths.pro
Normal file
@@ -0,0 +1,13 @@
|
||||
#This file has to be included after CONFIG has been adjusted and before the path variables are used
|
||||
#It has to be adjusted to your paths
|
||||
|
||||
CONFIG(qwt){
|
||||
LIBS += -L/opt/qwt/lib/ -lqwt -lutil
|
||||
INCLUDEPATH += /opt/qwt/include
|
||||
}
|
||||
|
||||
|
||||
CONFIG(python){
|
||||
LIBS += -lpython3.4m
|
||||
INCLUDEPATH += /opt/python/include/python3.4m
|
||||
}
|
||||
61
analyzer/analyzer/preferences.ui
Normal file
61
analyzer/analyzer/preferences.ui
Normal file
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Preferences</class>
|
||||
<widget class="QWidget" name="Preferences">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
<widget class="QGroupBox" name="verticalGroupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>291</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Color-Grouping:</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rb_grouping_phase">
|
||||
<property name="text">
|
||||
<string>Phase-Type</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rb_grouping_transaction">
|
||||
<property name="text">
|
||||
<string>Transaction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="rb_grouping_thread">
|
||||
<property name="text">
|
||||
<string>Thread</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
65
analyzer/analyzer/presentation/commenttreewidget.cpp
Normal file
65
analyzer/analyzer/presentation/commenttreewidget.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "commenttreewidget.h"
|
||||
#include <QTreeWidgetItem>
|
||||
#include <iostream>
|
||||
#include <QMenu>
|
||||
|
||||
void CommentTreeWidget::init(TraceNavigator *navigator)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
this->navigator = navigator;
|
||||
setColumnCount(2);
|
||||
setHeaderLabels(QStringList({"Time", "Comment"}));
|
||||
QObject::connect(navigator,SIGNAL(commentsChanged()),this, SLOT(commentsChanged()));
|
||||
QObject::connect(this,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(itemDoubleClicked(QTreeWidgetItem*,int)));
|
||||
QObject::connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ContextMenuRequested(QPoint)));
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
deleteComment = new QAction("Delete comment",this);
|
||||
printComments();
|
||||
}
|
||||
|
||||
void CommentTreeWidget::commentsChanged()
|
||||
{
|
||||
clear();
|
||||
printComments();
|
||||
}
|
||||
|
||||
void CommentTreeWidget::printComments()
|
||||
{
|
||||
for(const auto &pair: navigator->getComments())
|
||||
{
|
||||
const Comment &comment = pair.second;
|
||||
QTreeWidgetItem* item = new CommentTreeItem(this,comment);
|
||||
addTopLevelItem(item);
|
||||
}
|
||||
resizeColumnToContents(0);
|
||||
}
|
||||
|
||||
void CommentTreeWidget::itemDoubleClicked(QTreeWidgetItem *item, int /*column*/)
|
||||
{
|
||||
CommentTreeItem* commentItem = static_cast<CommentTreeItem*>(item);
|
||||
navigator->navigateToTime(commentItem->Time());
|
||||
}
|
||||
|
||||
void CommentTreeWidget::ContextMenuRequested(QPoint point)
|
||||
{
|
||||
QMenu contextMenu;
|
||||
contextMenu.addActions({deleteComment});
|
||||
QAction* selectedItem = contextMenu.exec(mapToGlobal(point));
|
||||
|
||||
if(selectedItem)
|
||||
{
|
||||
for(QTreeWidgetItem *item: selectedItems())
|
||||
{
|
||||
CommentTreeItem *commentItem = static_cast<CommentTreeItem*>(item);
|
||||
navigator->removeCommentAtTime(commentItem->Time());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CommentTreeWidget::CommentTreeItem::CommentTreeItem(QTreeWidget *parent, const Comment &comment):QTreeWidgetItem(parent),comment(comment)
|
||||
{
|
||||
this->setText(0,prettyFormatTime(comment.Time()));
|
||||
this->setText(1,comment.Text());
|
||||
}
|
||||
38
analyzer/analyzer/presentation/commenttreewidget.h
Normal file
38
analyzer/analyzer/presentation/commenttreewidget.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef COMMENTTREEWIDGET_H
|
||||
#define COMMENTTREEWIDGET_H
|
||||
#include <QTreeWidget>
|
||||
#include <QTreeWidgetItem>
|
||||
#include <QAction>
|
||||
#include "businessObjects/comment.h"
|
||||
#include "tracenavigator.h"
|
||||
|
||||
class CommentTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CommentTreeWidget(QWidget *parent = 0) : QTreeWidget(parent),isInitialized(false){}
|
||||
void init(TraceNavigator* navigator);
|
||||
|
||||
public Q_SLOTS:
|
||||
void commentsChanged();
|
||||
void itemDoubleClicked(QTreeWidgetItem * item, int column);
|
||||
void ContextMenuRequested(QPoint point);
|
||||
|
||||
private:
|
||||
bool isInitialized;
|
||||
TraceNavigator *navigator;
|
||||
void printComments();
|
||||
QAction* deleteComment;
|
||||
|
||||
class CommentTreeItem : public QTreeWidgetItem
|
||||
{
|
||||
private:
|
||||
Comment comment;
|
||||
public:
|
||||
CommentTreeItem(QTreeWidget * parent, const Comment &comment);
|
||||
traceTime Time() {return comment.Time();}
|
||||
};
|
||||
};
|
||||
|
||||
#endif // COMMENTTREEWIDGET_H
|
||||
90
analyzer/analyzer/presentation/debugmessagetreewidget.cpp
Normal file
90
analyzer/analyzer/presentation/debugmessagetreewidget.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
#include "debugmessagetreewidget.h"
|
||||
#include <QGuiApplication>
|
||||
#include <qtooltip.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void DebugMessageTreeWidget::init(TraceNavigator *navigator, TracePlot *traceplot)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
arrangeUiSettings();
|
||||
connect(navigator,SIGNAL(currentTraceTimeChanged()),this,SLOT(currentTraceTimeChanged()));
|
||||
connect(navigator,SIGNAL(selectedTransactionsChanged()),this,SLOT(selectedTransactionChanged()));
|
||||
this->traceplot = traceplot;
|
||||
this->navigator = navigator;
|
||||
currentTraceTimeChanged();
|
||||
}
|
||||
|
||||
void DebugMessageTreeWidget::arrangeUiSettings()
|
||||
{
|
||||
QFont font = QGuiApplication::font();
|
||||
font.setPointSize(10);
|
||||
this->setFont(font);
|
||||
setColumnCount(2);
|
||||
setHeaderLabels(QStringList({"Time", "Message"}));
|
||||
}
|
||||
|
||||
void DebugMessageTreeWidget::selectedTransactionChanged()
|
||||
{
|
||||
if(navigator->hasSelectedTransactions())
|
||||
{
|
||||
Timespan span = navigator->getSpanCoveredBySelectedTransaction();
|
||||
showDebugMessages(navigator->TraceFile().getDebugMessagesInTimespan(span));
|
||||
}
|
||||
else
|
||||
{
|
||||
showDebugMessages(navigator->TraceFile().getDebugMessagesInTimespan(traceplot->GetCurrentTimespan()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DebugMessageTreeWidget::currentTraceTimeChanged()
|
||||
{
|
||||
if(!navigator->hasSelectedTransactions())
|
||||
showDebugMessages(navigator->TraceFile().getDebugMessagesInTimespan(traceplot->GetCurrentTimespan()));
|
||||
}
|
||||
|
||||
void DebugMessageTreeWidget::showDebugMessages(const vector<Comment>& comments)
|
||||
{
|
||||
clear();
|
||||
if(comments.empty())
|
||||
return;
|
||||
|
||||
traceTime currentTime = -1;
|
||||
for(Comment comment: comments)
|
||||
{
|
||||
if(currentTime != comment.Time())
|
||||
{
|
||||
addTopLevelItem(new QTreeWidgetItem({prettyFormatTime(comment.Time()), formatDebugMessage(comment.Text())}));
|
||||
currentTime = comment.Time();
|
||||
}
|
||||
else
|
||||
{
|
||||
addTopLevelItem(new QTreeWidgetItem({"", formatDebugMessage(comment.Text())}));
|
||||
}
|
||||
}
|
||||
|
||||
this->resizeColumnToContents(0);
|
||||
this->scrollToTop();
|
||||
}
|
||||
|
||||
QString DebugMessageTreeWidget::formatDebugMessage(const QString &message)
|
||||
{
|
||||
QString formattedMessage = message;
|
||||
formattedMessage.replace(hexAdressMatcher,"");
|
||||
formattedMessage.replace(timeAnnotationMatcher,"");
|
||||
formattedMessage.replace("\t"," ");
|
||||
return formattedMessage;
|
||||
}
|
||||
|
||||
void DebugMessageTreeWidget::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
QTreeWidgetItem* itemUnderCursor = itemAt(event->pos());
|
||||
if(itemUnderCursor != NULL)
|
||||
{
|
||||
QToolTip::showText(this->mapToGlobal(event->pos()), itemUnderCursor->text(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
37
analyzer/analyzer/presentation/debugmessagetreewidget.h
Normal file
37
analyzer/analyzer/presentation/debugmessagetreewidget.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef DEBUGMESSAGELISTWIDGET_H
|
||||
#define DEBUGMESSAGELISTWIDGET_H
|
||||
#include <QTreeWidget>
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
#include <QRegularExpression>
|
||||
#include <QMouseEvent>
|
||||
#include "businessObjects/comment.h"
|
||||
#include "tracenavigator.h"
|
||||
#include "traceplot.h"
|
||||
|
||||
class DebugMessageTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DebugMessageTreeWidget(QWidget *parent = 0) : QTreeWidget(parent),isInitialized(false), timeAnnotationMatcher(QString("@[0-9]+ n?s")), hexAdressMatcher(QString("0x[0-9,a-f]+")) {}
|
||||
void init(TraceNavigator* navigator, TracePlot* traceplot);
|
||||
|
||||
void showDebugMessages(const std::vector<Comment>& comments);
|
||||
void arrangeUiSettings();
|
||||
|
||||
public Q_SLOTS:
|
||||
void currentTraceTimeChanged();
|
||||
void selectedTransactionChanged();
|
||||
|
||||
private:
|
||||
bool isInitialized;
|
||||
TracePlot* traceplot;
|
||||
TraceNavigator* navigator;
|
||||
QRegularExpression timeAnnotationMatcher;
|
||||
QRegularExpression hexAdressMatcher;
|
||||
QString formatDebugMessage(const QString& message);
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
};
|
||||
|
||||
#endif // DEBUGMESSAGELISTWIDGET_H
|
||||
238
analyzer/analyzer/presentation/pornotracescroller.cpp
Normal file
238
analyzer/analyzer/presentation/pornotracescroller.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
#include <qwt_plot_zoneitem.h>
|
||||
#include <QWheelEvent>
|
||||
#include <QMouseEvent>
|
||||
#include "pornotracescroller.h"
|
||||
#include "traceplotitem.h"
|
||||
#include "util/engineeringScaleDraw.h"
|
||||
|
||||
PornoTraceScroller::PornoTraceScroller(QWidget *parent):
|
||||
QwtPlot(parent),isInitialized(false),drawingProperties(false, false, ColorGrouping::Transaction)
|
||||
{
|
||||
setAxisScaleDraw(xBottom,new EngineeringScaleDraw);
|
||||
canvas()->setCursor(Qt::ArrowCursor);
|
||||
canvasClip = new QwtPlotZoneItem();
|
||||
canvasClip->setZ(2);
|
||||
canvasClip->attach(this);
|
||||
}
|
||||
|
||||
void PornoTraceScroller::init(TraceNavigator *navigator, TracePlot *tracePlot)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
|
||||
this -> navigator = navigator;
|
||||
connectNavigatorQ_SIGNALS();
|
||||
|
||||
setUpAxis();
|
||||
setUpDrawingProperties();
|
||||
setUpTracePlotItem();
|
||||
getAndDrawComments();
|
||||
|
||||
this->tracePlot = tracePlot;
|
||||
QObject::connect(tracePlot,SIGNAL(tracePlotZoomChanged()),this,SLOT(tracePlotZoomChanged()));
|
||||
tracePlotZoomChanged();
|
||||
|
||||
QObject::connect(tracePlot,SIGNAL(colorGroupingChanged(ColorGrouping)),this,SLOT(colorGroupingChanged(ColorGrouping)));
|
||||
}
|
||||
|
||||
|
||||
void PornoTraceScroller::setUpTracePlotItem()
|
||||
{
|
||||
TracePlotItem *tracePlotItem = new TracePlotItem(transactions,*navigator, drawingProperties);
|
||||
tracePlotItem->setZ(1);
|
||||
tracePlotItem->attach(this);
|
||||
}
|
||||
|
||||
void PornoTraceScroller::setUpDrawingProperties()
|
||||
{
|
||||
unsigned int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks;
|
||||
drawingProperties.numberOfBanks = numberOfBanks;
|
||||
drawingProperties.yValResponse = numberOfBanks;
|
||||
drawingProperties.yValRequest = numberOfBanks + 1;
|
||||
drawingProperties.yValCommandBus = -3;
|
||||
drawingProperties.yValDataBus = -4;
|
||||
}
|
||||
|
||||
|
||||
void PornoTraceScroller::setUpAxis()
|
||||
{
|
||||
setAxisScale(yLeft, -1, navigator -> GeneralTraceInfo().numberOfBanks + 2, 1.0);
|
||||
axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Labels, false );
|
||||
axisScaleDraw(yLeft)->enableComponent(QwtAbstractScaleDraw::Ticks, false );
|
||||
}
|
||||
|
||||
void PornoTraceScroller::connectNavigatorQ_SIGNALS()
|
||||
{
|
||||
QObject::connect(navigator,SIGNAL(currentTraceTimeChanged()), this, SLOT(currentTraceTimeChanged()));
|
||||
QObject::connect(navigator,SIGNAL(commentsChanged()),this,SLOT(commentsChanged()));
|
||||
QObject::connect(navigator,SIGNAL(selectedTransactionsChanged()),this,SLOT(selectedTransactionsChanged()));
|
||||
}
|
||||
|
||||
Timespan PornoTraceScroller::GetCurrentTimespan()
|
||||
{
|
||||
traceTime deltaOnTracePlot = navigator->GeneralTraceInfo().span.End() - tracePlot->ZoomLevel();
|
||||
traceTime deltaOnPornoTraceScroller = navigator->GeneralTraceInfo().span.End() - zoomLevel;
|
||||
|
||||
traceTime newBegin = static_cast<traceTime> (tracePlot->GetCurrentTimespan().Begin() * (1.0*deltaOnPornoTraceScroller)/deltaOnTracePlot);
|
||||
Timespan span(newBegin, newBegin + zoomLevel);
|
||||
|
||||
if(span.Begin() < 0)
|
||||
span.shift(-span.Begin());
|
||||
else if(span.End() > navigator->GeneralTraceInfo().span.End())
|
||||
span.shift(navigator->GeneralTraceInfo().span.End() - span.End());
|
||||
return span;
|
||||
}
|
||||
|
||||
|
||||
void PornoTraceScroller::getAndDrawComments()
|
||||
{
|
||||
for(const auto &pair: navigator->getComments())
|
||||
{
|
||||
const Comment &comment = pair.second;
|
||||
QwtPlotMarker *maker = new QwtPlotMarker();
|
||||
maker->setXValue(static_cast<double>(comment.Time()));
|
||||
maker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
|
||||
maker->setLinePen(QColor(Qt::blue),2);
|
||||
maker->attach(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Q_SLOTS
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void PornoTraceScroller::selectedTransactionsChanged()
|
||||
{
|
||||
replot();
|
||||
}
|
||||
|
||||
void PornoTraceScroller::colorGroupingChanged(ColorGrouping colorGrouping)
|
||||
{
|
||||
drawingProperties.colorGrouping = colorGrouping;
|
||||
replot();
|
||||
}
|
||||
|
||||
void PornoTraceScroller::currentTraceTimeChanged()
|
||||
{
|
||||
Timespan spanOnTracePlot = tracePlot->GetCurrentTimespan();
|
||||
canvasClip->setInterval(spanOnTracePlot.Begin(), spanOnTracePlot.End());
|
||||
Timespan span = GetCurrentTimespan();
|
||||
transactions = navigator->TraceFile().getTransactionsInTimespan(span);
|
||||
setAxisScale(xBottom,span.Begin(),span.End());
|
||||
replot();
|
||||
}
|
||||
|
||||
void PornoTraceScroller::commentsChanged()
|
||||
{
|
||||
detachItems(QwtPlotItem::Rtti_PlotMarker);
|
||||
getAndDrawComments();
|
||||
replot();
|
||||
}
|
||||
|
||||
void PornoTraceScroller::tracePlotZoomChanged()
|
||||
{
|
||||
zoomLevel = tracePlot->ZoomLevel()*tracePlotEnlargementFactor;
|
||||
if(zoomLevel > navigator->GeneralTraceInfo().span.timeCovered())
|
||||
zoomLevel = navigator->GeneralTraceInfo().span.timeCovered();
|
||||
}
|
||||
|
||||
bool PornoTraceScroller::eventFilter( QObject *object, QEvent *event )
|
||||
{
|
||||
if(object == canvas())
|
||||
{
|
||||
static bool clipDragged = false;
|
||||
static bool leftMousePressed = false;
|
||||
static int mouseDownX = 0;
|
||||
static traceTime mouseDownTracePlotTime = 0;
|
||||
|
||||
switch(event->type())
|
||||
{
|
||||
case QEvent::Wheel :
|
||||
{
|
||||
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
|
||||
traceTime offset;
|
||||
int speed = 4;
|
||||
(wheelEvent->delta() > 0) ? offset = -zoomLevel * speed : offset = zoomLevel * speed;
|
||||
navigator->navigateToTime(navigator->CurrentTraceTime() + offset);
|
||||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonDblClick:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
traceTime time = invTransform(xBottom, mouseEvent->x());
|
||||
navigator->navigateToTime(time);
|
||||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
|
||||
if(mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
canvas()->setCursor(Qt::ClosedHandCursor);
|
||||
leftMousePressed = true;
|
||||
mouseDownTracePlotTime = tracePlot->GetCurrentTimespan().Middle();
|
||||
mouseDownX = mouseEvent->x();
|
||||
if(tracePlot->GetCurrentTimespan().contains(invTransform(xBottom, mouseEvent->x())))
|
||||
clipDragged = true;
|
||||
else
|
||||
clipDragged = false;
|
||||
return true;
|
||||
}
|
||||
else if(mouseEvent->button() == Qt::RightButton)
|
||||
{
|
||||
navigator->navigateToTime(static_cast<traceTime>(invTransform(xBottom, mouseEvent->x())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if(mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
clipDragged = false;
|
||||
leftMousePressed = false;
|
||||
canvas()->setCursor(Qt::ArrowCursor);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
if(leftMousePressed)
|
||||
{
|
||||
if(clipDragged)
|
||||
{
|
||||
double clipWidth = transform(xBottom, tracePlot->ZoomLevel()) - transform(xBottom, 0);
|
||||
|
||||
if(mouseEvent->x() < clipWidth/2)
|
||||
{
|
||||
navigator->navigateToTime(0);
|
||||
}
|
||||
else if(mouseEvent->x() > canvas()->width() - clipWidth/2)
|
||||
{
|
||||
navigator->navigateToTime(navigator->GeneralTraceInfo().span.End());
|
||||
}
|
||||
else
|
||||
{
|
||||
traceTime time = static_cast<traceTime>((mouseEvent->x() - clipWidth/2) /
|
||||
(canvas()->width() - clipWidth) * (navigator->GeneralTraceInfo().span.End() - tracePlot->ZoomLevel()));
|
||||
navigator->navigateToTime(time);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
traceTime deltaTime = invTransform(xBottom, mouseDownX) - invTransform(xBottom, mouseEvent->x());
|
||||
navigator->navigateToTime(mouseDownTracePlotTime + deltaTime);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
46
analyzer/analyzer/presentation/pornotracescroller.h
Normal file
46
analyzer/analyzer/presentation/pornotracescroller.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef PORNOTRACESCROLLER_H
|
||||
#define PORNOTRACESCROLLER_H
|
||||
|
||||
#include <qwt_plot.h>
|
||||
#include <qwt_plot_zoneitem.h>
|
||||
#include <vector>
|
||||
#include "presentation/tracenavigator.h"
|
||||
#include "traceplot.h"
|
||||
|
||||
|
||||
class PornoTraceScroller : public QwtPlot
|
||||
{
|
||||
Q_OBJECT
|
||||
private:
|
||||
std::vector<std::shared_ptr<Transaction>> transactions;
|
||||
bool isInitialized;
|
||||
TraceNavigator* navigator;
|
||||
TracePlot* tracePlot;
|
||||
constexpr static int tracePlotEnlargementFactor = 4;
|
||||
void setUpTracePlotItem();
|
||||
void setUpDrawingProperties();
|
||||
void setUpAxis();
|
||||
void connectNavigatorQ_SIGNALS();
|
||||
|
||||
|
||||
void getAndDrawComments();
|
||||
QwtPlotZoneItem *canvasClip;
|
||||
traceTime zoomLevel;
|
||||
bool eventFilter( QObject *object, QEvent *event );
|
||||
TraceDrawingProperties drawingProperties;
|
||||
|
||||
public:
|
||||
PornoTraceScroller(QWidget *parent = NULL);
|
||||
void init(TraceNavigator* navigator, TracePlot* tracePlot);
|
||||
Timespan GetCurrentTimespan();
|
||||
|
||||
public Q_SLOTS:
|
||||
void currentTraceTimeChanged();
|
||||
void commentsChanged();
|
||||
void tracePlotZoomChanged();
|
||||
void selectedTransactionsChanged();
|
||||
void colorGroupingChanged(ColorGrouping colorgrouping);
|
||||
|
||||
};
|
||||
|
||||
#endif // PORNOTRACESCROLLER_H
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "selectedtransactiontreewidget.h"
|
||||
|
||||
|
||||
|
||||
void SelectedTransactionTreeWidget::selectedTransactionsChanged()
|
||||
{
|
||||
this->clear();
|
||||
for(const auto& transaction : navigator->SelectedTransactions())
|
||||
{
|
||||
AppendTransaction(transaction);
|
||||
}
|
||||
expandAll();
|
||||
resizeColumnToContents(0);
|
||||
}
|
||||
|
||||
void SelectedTransactionTreeWidget::init(TraceNavigator *navigator)
|
||||
{
|
||||
TransactionTreeWidget::init(navigator);
|
||||
QObject::connect(navigator, SIGNAL(selectedTransactionsChanged()), this, SLOT(selectedTransactionsChanged()));
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef SELECTEDTRANSACTIONTREEWIDGET_H
|
||||
#define SELECTEDTRANSACTIONTREEWIDGET_H
|
||||
#include "transactiontreewidget.h"
|
||||
|
||||
class SelectedTransactionTreeWidget : public TransactionTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
bool isInitialized;
|
||||
public:
|
||||
SelectedTransactionTreeWidget(QWidget *parent = 0) : TransactionTreeWidget(parent), isInitialized(false){}
|
||||
virtual void init(TraceNavigator* navigator);
|
||||
|
||||
public Q_SLOTS:
|
||||
void selectedTransactionsChanged();
|
||||
|
||||
};
|
||||
|
||||
#endif // SELECTEDTRANSACTIONTREEWIDGET_H
|
||||
24
analyzer/analyzer/presentation/tracePlotMouseLabel.cpp
Normal file
24
analyzer/analyzer/presentation/tracePlotMouseLabel.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "tracePlotMouseLabel.h"
|
||||
#include "businessObjects/tracetime.h"
|
||||
|
||||
void TracePlotMouseLabel::setMode(MouseLabelMode mode)
|
||||
{
|
||||
this->mode = mode;
|
||||
}
|
||||
|
||||
QwtText TracePlotMouseLabel::trackerText(const QPoint &point) const
|
||||
{
|
||||
if(mode == MouseLabelMode::AbsoluteTime)
|
||||
{
|
||||
traceTime mouseTime = static_cast<traceTime>(traceplot->invTransform(traceplot->xBottom, point.x()));
|
||||
return QwtText(prettyFormatTime(alignToClk(mouseTime,clkPeriod)) + "(" + formatInClks(mouseTime,clkPeriod) + ")");
|
||||
}
|
||||
else if(mode == MouseLabelMode::Timedifference)
|
||||
{
|
||||
return QwtText(formatInClks(timeDifferenceSpan.timeCovered(),clkPeriod));
|
||||
}
|
||||
else
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
}
|
||||
28
analyzer/analyzer/presentation/tracePlotMouseLabel.h
Normal file
28
analyzer/analyzer/presentation/tracePlotMouseLabel.h
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef TRACEPLOTPICKER_H
|
||||
#define TRACEPLOTPICKER_H
|
||||
|
||||
#include <qwt_plot_picker.h>
|
||||
#include "traceplot.h"
|
||||
|
||||
enum class MouseLabelMode{AbsoluteTime, Timedifference};
|
||||
|
||||
class TracePlotMouseLabel : public QwtPlotPicker
|
||||
{
|
||||
public:
|
||||
TracePlotMouseLabel(TracePlot* traceplot, unsigned int clkPeriod, Timespan& timeDifferenceSpan):
|
||||
QwtPlotPicker(QwtPlot::xBottom, QwtPlot::yLeft,QwtPlotPicker::VLineRubberBand,
|
||||
QwtPicker::AlwaysOn, traceplot->canvas()),
|
||||
mode(MouseLabelMode::AbsoluteTime),traceplot(traceplot),clkPeriod(clkPeriod), timeDifferenceSpan(timeDifferenceSpan){}
|
||||
|
||||
void setMode(MouseLabelMode mode);
|
||||
protected:
|
||||
virtual QwtText trackerText(const QPoint &point) const;
|
||||
|
||||
private:
|
||||
MouseLabelMode mode;
|
||||
TracePlot* traceplot;
|
||||
unsigned int clkPeriod;
|
||||
Timespan& timeDifferenceSpan;
|
||||
};
|
||||
|
||||
#endif // TRACEPLOTPICKER_H
|
||||
135
analyzer/analyzer/presentation/tracedrawing.cpp
Normal file
135
analyzer/analyzer/presentation/tracedrawing.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "tracedrawing.h"
|
||||
|
||||
void drawVerticalLine(QPainter *painter, int xPos, const QRectF &canvasRect)
|
||||
{
|
||||
/* P1 (xPos,lowerCanvasYBorder)
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* |
|
||||
* P2 (xPos,upperCanvasYBorder)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
QPoint P1(xPos,static_cast<int>(canvasRect.top()));
|
||||
QPoint P2(xPos,static_cast<int>(canvasRect.bottom()));
|
||||
painter->drawLine(QLine(P1,P2));
|
||||
}
|
||||
|
||||
void drawDoubleArrow(QPainter *painter, int xFrom, int xTo, int y)
|
||||
{
|
||||
|
||||
/* P1 P3
|
||||
// / \
|
||||
// / {text} \
|
||||
// from (-------------------------------------------) to
|
||||
// \ /
|
||||
// \ /
|
||||
// P2 P4
|
||||
*/
|
||||
|
||||
QPoint from(xFrom,y);
|
||||
QPoint to(xTo,y);
|
||||
QPoint P1(xFrom+10,y-5);
|
||||
QPoint P2(xFrom+10,y+5);
|
||||
QPoint P3(xTo-10,y-5);
|
||||
QPoint P4(xTo-10,y+5);
|
||||
|
||||
painter->drawLine(from,to);
|
||||
painter->drawLine(P1,from);
|
||||
painter->drawLine(P2,from);
|
||||
painter->drawLine(P3,to);
|
||||
painter->drawLine(P4,to);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void drawDoubleArrow(QPainter *painter, int xFrom, int xTo, int y, const QString &text, const QColor &textColor)
|
||||
{
|
||||
drawDoubleArrow(painter, xFrom, xTo, y);
|
||||
drawText(painter, text, QPoint((xTo + xFrom) / 2, y), TextPositioning::topCenter, textColor);
|
||||
}
|
||||
|
||||
void drawHexagon(QPainter *painter, const QPoint& from, const QPoint& to, double height)
|
||||
{
|
||||
// {text}
|
||||
// P1------------------------P2
|
||||
// From / \ To
|
||||
// \ /
|
||||
// P4-------------------------P3
|
||||
|
||||
int offset = 10;
|
||||
if( (to.x() - from.x()) <= 20)
|
||||
{
|
||||
offset = 5;
|
||||
}
|
||||
if( (to.x() - from.x()) <= 10)
|
||||
{
|
||||
offset = 2;
|
||||
}
|
||||
if( (to.x() - from.x()) <= 4)
|
||||
{
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
QPointF P1(from.x()+offset , from.y()-height/2);
|
||||
QPointF P2(to.x() -offset , to.y() -height/2);
|
||||
QPointF P3(to.x() -offset , to.y() +height/2);
|
||||
QPointF P4(from.x()+offset , from.y()+height/2);
|
||||
|
||||
QPolygonF polygon;
|
||||
polygon << from
|
||||
<< P1
|
||||
<< P2
|
||||
<< to
|
||||
<< P3
|
||||
<< P4;
|
||||
|
||||
painter->drawPolygon(polygon);
|
||||
}
|
||||
|
||||
void drawText(QPainter *painter, const QString &text, const QPoint &position, const TextPositioning &positioning, const QColor &textColor)
|
||||
{
|
||||
//*--------------*
|
||||
//| | |
|
||||
//|------x-------|
|
||||
//| | |
|
||||
//*--------------*
|
||||
|
||||
QPen saved = painter->pen();
|
||||
painter->setPen(QPen(textColor));
|
||||
QFontMetrics fm = painter->fontMetrics();
|
||||
QPoint offset(fm.width(text), fm.height());
|
||||
QRect rect(position - offset, position + offset);
|
||||
|
||||
int flags;
|
||||
switch(positioning)
|
||||
{
|
||||
case TextPositioning::topRight:
|
||||
flags = Qt::AlignRight | Qt::AlignTop;
|
||||
break;
|
||||
case TextPositioning::bottomRight:
|
||||
flags = Qt::AlignRight | Qt::AlignBottom;
|
||||
break;
|
||||
case TextPositioning::bottomLeft:
|
||||
flags = Qt::AlignLeft | Qt::AlignBottom;
|
||||
break;
|
||||
case TextPositioning::topCenter:
|
||||
flags = Qt::AlignHCenter | Qt::AlignTop;
|
||||
break;
|
||||
case TextPositioning::bottomCenter:
|
||||
flags = Qt::AlignHCenter | Qt::AlignBottom;
|
||||
break;
|
||||
case TextPositioning::centerCenter:
|
||||
flags = Qt::AlignHCenter | Qt::AlignCenter;
|
||||
break;
|
||||
case TextPositioning::topLeft:default:
|
||||
flags = Qt::AlignLeft | Qt::AlignTop;
|
||||
break;
|
||||
}
|
||||
|
||||
painter->drawText(rect, flags, text);
|
||||
painter->setPen(saved);
|
||||
}
|
||||
17
analyzer/analyzer/presentation/tracedrawing.h
Normal file
17
analyzer/analyzer/presentation/tracedrawing.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef TRACEDRAWING_H
|
||||
#define TRACEDRAWING_H
|
||||
|
||||
#include <QPainter>
|
||||
#include <QRectF>
|
||||
#include <QColor>
|
||||
#include <QString>
|
||||
|
||||
enum class TextPositioning{topRight, topLeft, bottomRight, bottomLeft, topCenter, bottomCenter, centerCenter};
|
||||
|
||||
void drawVerticalLine(QPainter *painter, int xPos, const QRectF &canvasRect);
|
||||
void drawDoubleArrow(QPainter *painter, int xFrom, int xTo, int y);
|
||||
void drawDoubleArrow(QPainter *painter, int xFrom, int xTo, int y, const QString &text, const QColor &textColor = QColor(Qt::black));
|
||||
void drawHexagon(QPainter *painter, const QPoint& from, const QPoint& to, double height);
|
||||
void drawText(QPainter *painter, const QString &text, const QPoint &position, const TextPositioning &positioning, const QColor &textColor = QColor(Qt::black));
|
||||
|
||||
#endif // TRACEDRAWING_H
|
||||
43
analyzer/analyzer/presentation/tracedrawingproperties.h
Normal file
43
analyzer/analyzer/presentation/tracedrawingproperties.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef TRACECOLLECTIONDRAWINGPROPERTIES_H
|
||||
#define TRACECOLLECTIONDRAWINGPROPERTIES_H
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
#include <map>
|
||||
#include <QHash>
|
||||
#include "tracedrawing.h"
|
||||
|
||||
enum class ColorGrouping {PhaseType, Transaction, Thread};
|
||||
|
||||
struct TraceDrawingProperties
|
||||
{
|
||||
bool drawText;
|
||||
bool drawBorder;
|
||||
ColorGrouping colorGrouping;
|
||||
int yValResponse;
|
||||
int yValRequest;
|
||||
int yValCommandBus;
|
||||
int yValDataBus;
|
||||
unsigned int numberOfBanks;
|
||||
|
||||
TraceDrawingProperties() : drawText(true), drawBorder(true), colorGrouping(ColorGrouping::Transaction){}
|
||||
TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping) : drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping){}
|
||||
TraceDrawingProperties(bool drawText, bool drawBorder, ColorGrouping colorGrouping, int yValResponse,int yValRequest, int yValCommandBus,int yValDataBus, unsigned int numberOfBanks) :
|
||||
drawText(drawText), drawBorder(drawBorder), colorGrouping(colorGrouping), yValResponse(yValResponse), yValRequest(yValRequest), yValCommandBus(yValCommandBus),yValDataBus(yValDataBus),numberOfBanks(numberOfBanks){}
|
||||
|
||||
QHash<int,QString> getLabels() const
|
||||
{
|
||||
QHash<int,QString> result;
|
||||
for(unsigned int i=0; i<numberOfBanks; i++)
|
||||
{
|
||||
result[i] = QString("Bank ") + QString::number(i);
|
||||
}
|
||||
|
||||
result[yValCommandBus] = "Cmd Bus";
|
||||
result[yValResponse] = "RESP";
|
||||
result[yValRequest] = "REQ";
|
||||
result[yValDataBus] = "Data Bus";
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TRACECOLLECTIONDRAWINGPROPERTIES_H
|
||||
23
analyzer/analyzer/presentation/tracemetrictreewidget.cpp
Normal file
23
analyzer/analyzer/presentation/tracemetrictreewidget.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "tracemetrictreewidget.h"
|
||||
|
||||
TraceMetricTreeWidget::TraceMetricTreeWidget(QWidget *parent) : QTreeWidget(parent)
|
||||
{
|
||||
setHeaderHidden(true);
|
||||
|
||||
}
|
||||
|
||||
void TraceMetricTreeWidget::addTraceMetricResults(const TraceCalculatedMetrics& result)
|
||||
{
|
||||
setColumnCount(2);
|
||||
|
||||
QTreeWidgetItem* top = new QTreeWidgetItem({result.getTraceName()});
|
||||
addTopLevelItem(top);
|
||||
|
||||
for(CalculatedMetric calculatedMetric : result.getCalculatedMetrics())
|
||||
{
|
||||
new QTreeWidgetItem(top,{calculatedMetric.getName() + QString(": ") + QString::number(calculatedMetric.getValue())});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
16
analyzer/analyzer/presentation/tracemetrictreewidget.h
Normal file
16
analyzer/analyzer/presentation/tracemetrictreewidget.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef TRACEMETRICTREEWIDGET_H
|
||||
#define TRACEMETRICTREEWIDGET_H
|
||||
#include <QTreeWidget>
|
||||
#include "businessObjects/tracecalculatedmetrics.h"
|
||||
|
||||
|
||||
class TraceMetricTreeWidget : public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TraceMetricTreeWidget(QWidget *parent = 0);
|
||||
void addTraceMetricResults(const TraceCalculatedMetrics& result);
|
||||
|
||||
};
|
||||
|
||||
#endif // TRACEMETRICTREEWIDGET_H
|
||||
243
analyzer/analyzer/presentation/tracenavigator.cpp
Normal file
243
analyzer/analyzer/presentation/tracenavigator.cpp
Normal file
@@ -0,0 +1,243 @@
|
||||
#include "tracenavigator.h"
|
||||
#include "vector"
|
||||
|
||||
using namespace std;
|
||||
|
||||
TraceNavigator::TraceNavigator(QString path, QObject * parent)
|
||||
: QObject(parent),traceFile(path,true), changesToCommitExist(false)
|
||||
{
|
||||
getCommentsFromDB();
|
||||
}
|
||||
|
||||
TraceNavigator::~TraceNavigator()
|
||||
{
|
||||
}
|
||||
|
||||
/* Navigation
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void TraceNavigator::navigateToTime(traceTime time)
|
||||
{
|
||||
if(time < 0)
|
||||
time = 0;
|
||||
else if(time>traceFile.getGeneralInfo().span.End())
|
||||
time = traceFile.getGeneralInfo().span.End();
|
||||
else
|
||||
{
|
||||
currentTraceTime = time;
|
||||
Q_EMIT currentTraceTimeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void TraceNavigator::navigateToTransaction(ID id)
|
||||
{
|
||||
navigateToTime(traceFile.getTransactionByID(id)->Span().Begin());
|
||||
}
|
||||
|
||||
|
||||
/* Comment and debug messages
|
||||
*
|
||||
*/
|
||||
void TraceNavigator::insertComment(const Comment &comment)
|
||||
{
|
||||
comments.emplace(comment.Time(), comment);
|
||||
changesToCommitExist = true;
|
||||
Q_EMIT commentsChanged();
|
||||
}
|
||||
|
||||
void TraceNavigator::removeCommentAtTime(traceTime time)
|
||||
{
|
||||
auto found = comments.find(time);
|
||||
if(found != comments.end())
|
||||
{
|
||||
comments.erase(found);
|
||||
changesToCommitExist = true;
|
||||
Q_EMIT commentsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* DB
|
||||
*
|
||||
*/
|
||||
|
||||
void TraceNavigator::commitChangesToDB()
|
||||
{
|
||||
vector<Comment> commentsToInsert;
|
||||
for(const auto& pair: comments)
|
||||
{
|
||||
commentsToInsert.push_back(pair.second);
|
||||
}
|
||||
|
||||
traceFile.updateComments(commentsToInsert);
|
||||
changesToCommitExist = false;
|
||||
}
|
||||
|
||||
void TraceNavigator::getCommentsFromDB()
|
||||
{
|
||||
for(const Comment& comment: traceFile.getComments())
|
||||
{
|
||||
comments.emplace(comment.Time(),comment);
|
||||
}
|
||||
}
|
||||
|
||||
void TraceNavigator::refreshData()
|
||||
{
|
||||
traceFile.refreshData();
|
||||
clearSelectedTransactions();
|
||||
navigateToTime(currentTraceTime);
|
||||
}
|
||||
|
||||
/* Transaction Selection
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void TraceNavigator::addSelectedTransactions(const vector<shared_ptr<Transaction>>& transactions)
|
||||
{
|
||||
for(const auto transaction : transactions)
|
||||
{
|
||||
selectedTransactions.push_back(transaction);
|
||||
}
|
||||
Q_EMIT selectedTransactionsChanged();
|
||||
}
|
||||
|
||||
void TraceNavigator::addSelectedTransaction(const shared_ptr<Transaction> &transaction)
|
||||
{
|
||||
selectedTransactions.push_back(transaction);
|
||||
Q_EMIT selectedTransactionsChanged();
|
||||
}
|
||||
|
||||
void TraceNavigator::addSelectedTransaction(ID id)
|
||||
{
|
||||
shared_ptr<Transaction> transaction = TraceFile().getTransactionByID(id);
|
||||
selectedTransactions.push_back(transaction);
|
||||
Q_EMIT selectedTransactionsChanged();
|
||||
}
|
||||
|
||||
void TraceNavigator::selectTransaction(ID id)
|
||||
{
|
||||
clearSelectedTransactions();
|
||||
addSelectedTransaction(id);
|
||||
navigateToTransaction(id);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectTransaction(const shared_ptr<Transaction> &transaction)
|
||||
{
|
||||
selectTransaction(transaction->Id());
|
||||
}
|
||||
|
||||
void TraceNavigator::selectNextTransaction()
|
||||
{
|
||||
if(selectedTransactions.empty() || selectedTransactions.front()->Id() == traceFile.getGeneralInfo().numberOfTransactions)
|
||||
selectFirstTransaction();
|
||||
else
|
||||
selectTransaction(selectedTransactions.front()->Id() + 1);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectPreviousTransaction()
|
||||
{
|
||||
if(selectedTransactions.empty() || selectedTransactions.front()->Id() == 1)
|
||||
selectLastTransaction();
|
||||
else
|
||||
selectTransaction(selectedTransactions.front()->Id() - 1);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectFirstTransaction()
|
||||
{
|
||||
selectTransaction(1);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectLastTransaction()
|
||||
{
|
||||
selectTransaction(traceFile.getGeneralInfo().numberOfTransactions);
|
||||
}
|
||||
|
||||
|
||||
void TraceNavigator::selectNextRefresh()
|
||||
{
|
||||
shared_ptr<Transaction> nextRefresh;
|
||||
|
||||
if(!SelectedTransactions().empty())
|
||||
nextRefresh = traceFile.getNextRefresh(SelectedTransactions().front()->Id());
|
||||
else
|
||||
nextRefresh = traceFile.getNextRefresh(0);
|
||||
|
||||
if(nextRefresh)
|
||||
selectTransaction(nextRefresh);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectNextActivate()
|
||||
{
|
||||
shared_ptr<Transaction> nextActivate;
|
||||
|
||||
if(!SelectedTransactions().empty())
|
||||
nextActivate = traceFile.getNextActivate(SelectedTransactions().front()->Id());
|
||||
else
|
||||
nextActivate = traceFile.getNextActivate(0);
|
||||
|
||||
if(nextActivate)
|
||||
selectTransaction(nextActivate);
|
||||
}
|
||||
|
||||
void TraceNavigator::selectNextPrecharge()
|
||||
{
|
||||
shared_ptr<Transaction> nextPrecharge;
|
||||
|
||||
if(!SelectedTransactions().empty())
|
||||
nextPrecharge = traceFile.getNextPrecharge(SelectedTransactions().front()->Id());
|
||||
else
|
||||
nextPrecharge = traceFile.getNextPrecharge(0);
|
||||
|
||||
if(nextPrecharge)
|
||||
selectTransaction(nextPrecharge);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool TraceNavigator::transactionIsSelected(const shared_ptr<Transaction> &transaction) const
|
||||
{
|
||||
return transactionIsSelected(transaction->Id());
|
||||
}
|
||||
|
||||
bool TraceNavigator::transactionIsSelected(ID id) const
|
||||
{
|
||||
for (const auto& transaction : selectedTransactions) {
|
||||
if(transaction->Id() == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TraceNavigator::clearSelectedTransactions()
|
||||
{
|
||||
if(hasSelectedTransactions())
|
||||
{
|
||||
selectedTransactions.clear();
|
||||
Q_EMIT selectedTransactionsChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool TraceNavigator::hasSelectedTransactions()
|
||||
{
|
||||
return !selectedTransactions.empty();
|
||||
}
|
||||
|
||||
Timespan TraceNavigator::getSpanCoveredBySelectedTransaction()
|
||||
{
|
||||
if(!hasSelectedTransactions())
|
||||
return Timespan(0,0);
|
||||
|
||||
traceTime begin = SelectedTransactions().at(0)->Span().Begin();
|
||||
traceTime end = SelectedTransactions().at(0)->Span().End();
|
||||
|
||||
for (const auto& transaction : selectedTransactions) {
|
||||
if(transaction->Span().End() > end)
|
||||
end = transaction->Span().End();
|
||||
}
|
||||
|
||||
return Timespan(begin,end);
|
||||
}
|
||||
81
analyzer/analyzer/presentation/tracenavigator.h
Normal file
81
analyzer/analyzer/presentation/tracenavigator.h
Normal file
@@ -0,0 +1,81 @@
|
||||
#ifndef TRACENAVIGATOR_H
|
||||
#define TRACENAVIGATOR_H
|
||||
#include <QObject>
|
||||
#include <vector>
|
||||
#include "data/tracedb.h"
|
||||
#include "businessObjects/generalinfo.h"
|
||||
#include "businessObjects/transaction.h"
|
||||
#include "businessObjects/comment.h"
|
||||
#include "memory"
|
||||
|
||||
/* Class to navigate through a tracefile
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
class TraceNavigator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
using CommentMap = std::map<traceTime, Comment>;
|
||||
|
||||
public:
|
||||
TraceNavigator(QString path, QObject * parent = 0);
|
||||
~TraceNavigator();
|
||||
|
||||
traceTime CurrentTraceTime() const{return currentTraceTime;}
|
||||
TraceDB& TraceFile(){return traceFile;}
|
||||
const GeneralInfo& GeneralTraceInfo() {return traceFile.getGeneralInfo();}
|
||||
|
||||
void navigateToTime(traceTime time);
|
||||
void navigateToTransaction(ID id);
|
||||
|
||||
/* Transaction selection
|
||||
* (selecting a single transactions also navigates to that transaction)
|
||||
*/
|
||||
void selectTransaction(ID id);
|
||||
void selectTransaction(const std::shared_ptr<Transaction> &transaction);
|
||||
void selectNextTransaction();
|
||||
void selectPreviousTransaction();
|
||||
void selectLastTransaction();
|
||||
void selectFirstTransaction();
|
||||
void selectNextRefresh();
|
||||
void selectNextActivate();
|
||||
void selectNextPrecharge();
|
||||
|
||||
void addSelectedTransactions(const std::vector<std::shared_ptr<Transaction>>& transactions);
|
||||
const std::vector<std::shared_ptr<Transaction>>& SelectedTransactions(){return selectedTransactions;}
|
||||
void addSelectedTransaction(const std::shared_ptr<Transaction> &Transaction);
|
||||
void addSelectedTransaction(ID id);
|
||||
void clearSelectedTransactions();
|
||||
bool hasSelectedTransactions();
|
||||
Timespan getSpanCoveredBySelectedTransaction();
|
||||
|
||||
bool transactionIsSelected(ID id) const;
|
||||
bool transactionIsSelected(const std::shared_ptr<Transaction> &Transaction) const;
|
||||
|
||||
void insertComment(const Comment& comment);
|
||||
const CommentMap& getComments(){return comments;}
|
||||
void removeCommentAtTime(traceTime time);
|
||||
|
||||
void commitChangesToDB();
|
||||
void refreshData();
|
||||
|
||||
Q_SIGNALS:
|
||||
void currentTraceTimeChanged();
|
||||
void selectedTransactionsChanged();
|
||||
void commentsChanged();
|
||||
|
||||
private:
|
||||
TraceDB traceFile;
|
||||
|
||||
//represents the current position in the tracefile
|
||||
//components drawing the tracefile center around that time
|
||||
traceTime currentTraceTime = 0;
|
||||
std::vector<std::shared_ptr<Transaction>> selectedTransactions;
|
||||
CommentMap comments;
|
||||
void getCommentsFromDB();
|
||||
bool changesToCommitExist;
|
||||
|
||||
};
|
||||
|
||||
#endif // TRACENAVIGATOR_H
|
||||
546
analyzer/analyzer/presentation/traceplot.cpp
Normal file
546
analyzer/analyzer/presentation/traceplot.cpp
Normal file
@@ -0,0 +1,546 @@
|
||||
#include <qwt_plot_grid.h>
|
||||
#include <QWheelEvent>
|
||||
#include <QMessageBox>
|
||||
#include <QMouseEvent>
|
||||
#include <iostream>
|
||||
#include <QMenu>
|
||||
#include <cmath>
|
||||
#include <QInputDialog>
|
||||
#include <QKeySequence>
|
||||
#include <QFileInfo>
|
||||
#include <qfiledialog.h>
|
||||
#include <iostream>
|
||||
#include <qwt_plot_renderer.h>
|
||||
|
||||
#include "tracePlotMouseLabel.h"
|
||||
#include "traceplot.h"
|
||||
#include "gototimedialog.h"
|
||||
#include "tracedrawing.h"
|
||||
#include "util/engineeringScaleDraw.h"
|
||||
#include "util/clkgrid.h"
|
||||
#include "util/customlabelscaledraw.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
TracePlot::TracePlot(QWidget *parent):
|
||||
QwtPlot(parent),isInitialized(false)
|
||||
{
|
||||
canvas()->setCursor(Qt::ArrowCursor);
|
||||
setUpActions();
|
||||
}
|
||||
|
||||
void TracePlot::setUpActions()
|
||||
{
|
||||
insertComment = new QAction("Insert comment",this);
|
||||
QObject::connect(insertComment, SIGNAL(triggered()), this, SLOT(on_insertComment()));
|
||||
|
||||
goToTime = new QAction("Go to time",this);
|
||||
QObject::connect(goToTime, SIGNAL(triggered()), this, SLOT(on_goToTime()));
|
||||
|
||||
goToTransaction = new QAction("Go to transaction", this);
|
||||
QObject::connect(goToTransaction, SIGNAL(triggered()), this, SLOT(on_goToTransaction()));
|
||||
|
||||
deselectAll = new QAction("Deselect all",this);
|
||||
QObject::connect(deselectAll, SIGNAL(triggered()), this, SLOT(on_deselectAll()));
|
||||
|
||||
goToPhase = new QAction("Go to phase", this);
|
||||
QObject::connect(goToPhase, SIGNAL(triggered()), this, SLOT(on_goToPhase()));
|
||||
|
||||
showQueryEditor = new QAction("Execute query",this);
|
||||
showQueryEditor->setShortcut(QKeySequence("ctrl+e"));
|
||||
addAction(showQueryEditor);
|
||||
QObject::connect(showQueryEditor,SIGNAL(triggered()),this,SLOT(on_executeQuery()));
|
||||
|
||||
selectNextRefresh = new QAction("Select next refresh",this);
|
||||
selectNextRefresh->setShortcut(QKeySequence("alt+r"));
|
||||
addAction(selectNextRefresh);
|
||||
QObject::connect(selectNextRefresh, SIGNAL(triggered()), this, SLOT(on_selectNextRefresh()));
|
||||
|
||||
selectNextActivate = new QAction("Select next activate",this);
|
||||
selectNextActivate->setShortcut(QKeySequence("alt+a"));
|
||||
addAction(selectNextActivate);
|
||||
QObject::connect(selectNextActivate, SIGNAL(triggered()), this, SLOT(on_selectNextActivate()));
|
||||
|
||||
selectNextPrecharge = new QAction("Select next precharge",this);
|
||||
selectNextPrecharge->setShortcut(QKeySequence("alt+p"));
|
||||
addAction(selectNextPrecharge);
|
||||
QObject::connect(selectNextPrecharge, SIGNAL(triggered()), this, SLOT(on_selectNextPrecharge()));
|
||||
|
||||
setColorGroupingPhase = new QAction("Group by Phase",this);
|
||||
addAction(setColorGroupingPhase);
|
||||
QObject::connect(setColorGroupingPhase, SIGNAL(triggered()), this, SLOT(on_colorGroupingPhase()));
|
||||
|
||||
setColorGroupingTransaction = new QAction("Group by Transaction",this);
|
||||
addAction(setColorGroupingTransaction);
|
||||
QObject::connect(setColorGroupingTransaction, SIGNAL(triggered()), this, SLOT(on_colorGroupingTransaction()));
|
||||
|
||||
setColorGroupingThread = new QAction("Group by Thread",this);
|
||||
addAction(setColorGroupingThread);
|
||||
QObject::connect(setColorGroupingThread, SIGNAL(triggered()), this, SLOT(on_colorGroupingThread()));
|
||||
|
||||
exportToPdf = new QAction("Export to SVG", this);
|
||||
addAction(exportToPdf);
|
||||
QObject::connect(exportToPdf, SIGNAL(triggered()), this, SLOT(on_exportToPDF()));
|
||||
|
||||
setUpContextMenu();
|
||||
}
|
||||
|
||||
void TracePlot::setUpContextMenu()
|
||||
{
|
||||
contextMenu = new QMenu(this);
|
||||
contextMenu->addActions({deselectAll});
|
||||
|
||||
QMenu* colorGroupingSubMenu = new QMenu("Group by",contextMenu);
|
||||
colorGroupingSubMenu->addActions({setColorGroupingTransaction, setColorGroupingPhase, setColorGroupingThread});
|
||||
contextMenu->addMenu(colorGroupingSubMenu);
|
||||
|
||||
QMenu* goToSubMenu = new QMenu("Go to",contextMenu);
|
||||
goToSubMenu->addActions({goToPhase,goToTransaction,goToTime});
|
||||
contextMenu->addMenu(goToSubMenu);
|
||||
|
||||
QMenu* selectSubMenu = new QMenu("Select",contextMenu);
|
||||
selectSubMenu->addActions({selectNextRefresh, selectNextActivate,selectNextPrecharge});
|
||||
contextMenu->addMenu(selectSubMenu);
|
||||
|
||||
contextMenu->addActions({showQueryEditor, insertComment,exportToPdf});
|
||||
}
|
||||
|
||||
void TracePlot::init(TraceNavigator* navigator)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
|
||||
this->navigator = navigator;
|
||||
connectNavigatorQ_SIGNALS();
|
||||
setUpDrawingProperties();
|
||||
setUpAxis();
|
||||
setUpGrid();
|
||||
setUpTracePlotItem();
|
||||
setUpZoom();
|
||||
setUpQueryEditor();
|
||||
mouseLabel = new TracePlotMouseLabel(this,navigator->GeneralTraceInfo().clkPeriod,this->mouseDownData.zoomSpan);
|
||||
getAndDrawComments();
|
||||
setZoomLevel(1000);
|
||||
replot();
|
||||
}
|
||||
|
||||
|
||||
void TracePlot::connectNavigatorQ_SIGNALS()
|
||||
{
|
||||
QObject::connect(navigator,SIGNAL(currentTraceTimeChanged()),this,SLOT(currentTraceTimeChanged()));
|
||||
QObject::connect(navigator,SIGNAL(selectedTransactionsChanged()),this,SLOT(selectedTransactionsChanged()));
|
||||
QObject::connect(navigator,SIGNAL(commentsChanged()),this,SLOT(commentsChanged()));
|
||||
}
|
||||
|
||||
void TracePlot::setUpDrawingProperties()
|
||||
{
|
||||
unsigned int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks;
|
||||
drawingProperties.numberOfBanks = numberOfBanks;
|
||||
drawingProperties.yValResponse = numberOfBanks;
|
||||
drawingProperties.yValRequest = numberOfBanks + 1;
|
||||
drawingProperties.yValCommandBus = -3;
|
||||
drawingProperties.yValDataBus = -4;
|
||||
}
|
||||
|
||||
|
||||
void TracePlot::setUpQueryEditor()
|
||||
{
|
||||
queryEditor = new QueryEditor(this);
|
||||
queryEditor->setWindowFlags(Qt::Window);
|
||||
queryEditor->setWindowTitle("Query " + QFileInfo(navigator->TraceFile().getPathToDB()).baseName());
|
||||
queryEditor->init(navigator);
|
||||
}
|
||||
|
||||
void TracePlot::setUpTracePlotItem()
|
||||
{
|
||||
tracePlotItem = new TracePlotItem(transactions,*navigator,drawingProperties);
|
||||
tracePlotItem->setZ(1);
|
||||
tracePlotItem->attach(this);
|
||||
}
|
||||
|
||||
void TracePlot::setUpGrid()
|
||||
{
|
||||
unsigned int clk = navigator->GeneralTraceInfo().clkPeriod;
|
||||
QwtPlotGrid *grid = new ClkGrid(clk, GridVisiblityClks*clk);
|
||||
grid->setZ(0);
|
||||
grid->attach(this);
|
||||
}
|
||||
|
||||
void TracePlot::setUpZoom()
|
||||
{
|
||||
minZoomLevel = minZoomClks * navigator->GeneralTraceInfo().clkPeriod;
|
||||
maxZoomLevel = maxZoomClks * navigator->GeneralTraceInfo().clkPeriod;
|
||||
textVisibilityZoomLevel = textVisibilityClks * navigator->GeneralTraceInfo().clkPeriod;
|
||||
zoomZone = new QwtPlotZoneItem();
|
||||
zoomZone->setZ(2);
|
||||
zoomZone->attach(this);
|
||||
zoomZone->setVisible(false);
|
||||
}
|
||||
|
||||
void TracePlot::setUpAxis()
|
||||
{
|
||||
int numberOfBanks = navigator -> GeneralTraceInfo().numberOfBanks;
|
||||
|
||||
setAxisScale(yLeft, -5, numberOfBanks + 2, 1.0);
|
||||
setAxisScaleDraw(yLeft,new CustomLabelScaleDraw(drawingProperties.getLabels()));
|
||||
|
||||
setAxisTitle(xBottom, "Time in ns");
|
||||
setAxisScaleDraw(xBottom, new EngineeringScaleDraw);
|
||||
}
|
||||
|
||||
Timespan TracePlot::GetCurrentTimespan()
|
||||
{
|
||||
Timespan span(navigator->CurrentTraceTime() - zoomLevel / 2, navigator->CurrentTraceTime() + zoomLevel / 2);
|
||||
if(span.Begin() < 0)
|
||||
span.shift(-span.Begin());
|
||||
else if(span.End() > navigator->GeneralTraceInfo().span.End())
|
||||
span.shift(navigator->GeneralTraceInfo().span.End() - span.End());
|
||||
return span;
|
||||
}
|
||||
|
||||
void TracePlot::getAndDrawComments()
|
||||
{
|
||||
for(const auto &pair: navigator->getComments())
|
||||
{
|
||||
const Comment &comment = pair.second;
|
||||
QwtPlotMarker *maker = new QwtPlotMarker();
|
||||
maker->setLabel(comment.Text());
|
||||
maker->setLabelOrientation(Qt::Vertical);
|
||||
maker->setLabelAlignment(Qt::AlignLeft | Qt::AlignBottom);
|
||||
maker->setXValue(static_cast<double>(comment.Time()));
|
||||
maker->setLineStyle(QwtPlotMarker::LineStyle::VLine);
|
||||
maker->setLinePen(QColor(Qt::blue),2);
|
||||
maker->attach(this);
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::enterZoomMode()
|
||||
{
|
||||
mouseDownData.mouseIsDownForZooming = true;
|
||||
mouseLabel->setMode(MouseLabelMode::Timedifference);
|
||||
zoomZone->setVisible(true);
|
||||
zoomZone->setInterval(mouseDownData.zoomSpan.Begin(),mouseDownData.zoomSpan.End());
|
||||
}
|
||||
|
||||
void TracePlot::exitZoomMode()
|
||||
{
|
||||
mouseDownData.mouseIsDownForZooming = false;
|
||||
mouseLabel->setMode(MouseLabelMode::AbsoluteTime);
|
||||
zoomZone->setVisible(false);
|
||||
}
|
||||
void TracePlot::zoomIn(traceTime zoomCenter)
|
||||
{
|
||||
setZoomLevel(zoomLevel * zoomFactor);
|
||||
traceTime time = zoomCenter + (GetCurrentTimespan().Middle() - zoomCenter) * zoomFactor;
|
||||
Q_EMIT tracePlotZoomChanged();
|
||||
navigator->navigateToTime(time);
|
||||
}
|
||||
|
||||
void TracePlot::zoomOut(traceTime zoomCenter)
|
||||
{
|
||||
setZoomLevel(zoomLevel / zoomFactor);
|
||||
Q_EMIT tracePlotZoomChanged();
|
||||
navigator->navigateToTime(static_cast<traceTime>(zoomCenter + (GetCurrentTimespan().Middle() - zoomCenter) / zoomFactor));
|
||||
}
|
||||
|
||||
void TracePlot::setZoomLevel(traceTime newZoomLevel)
|
||||
{
|
||||
zoomLevel = newZoomLevel;
|
||||
if(zoomLevel < minZoomLevel)
|
||||
zoomLevel = minZoomLevel;
|
||||
if(zoomLevel > navigator->GeneralTraceInfo().span.timeCovered())
|
||||
zoomLevel = navigator->GeneralTraceInfo().span.timeCovered();
|
||||
if(zoomLevel > maxZoomLevel)
|
||||
zoomLevel = maxZoomLevel;
|
||||
|
||||
if(zoomLevel < textVisibilityZoomLevel)
|
||||
drawingProperties.drawText = true;
|
||||
|
||||
if(zoomLevel > textVisibilityZoomLevel)
|
||||
drawingProperties.drawText = false;
|
||||
}
|
||||
|
||||
|
||||
/* Q_SLOTS
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void TracePlot::currentTraceTimeChanged()
|
||||
{
|
||||
transactions = navigator->TraceFile().getTransactionsInTimespan(GetCurrentTimespan());
|
||||
setAxisScale(xBottom,GetCurrentTimespan().Begin(),GetCurrentTimespan().End());
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::selectedTransactionsChanged()
|
||||
{
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::commentsChanged()
|
||||
{
|
||||
detachItems(QwtPlotItem::Rtti_PlotMarker);
|
||||
getAndDrawComments();
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::on_executeQuery()
|
||||
{
|
||||
queryEditor->show();
|
||||
}
|
||||
|
||||
void TracePlot::on_selectNextRefresh()
|
||||
{
|
||||
navigator->selectNextRefresh();
|
||||
}
|
||||
|
||||
void TracePlot::on_selectNextActivate()
|
||||
{
|
||||
navigator->selectNextActivate();
|
||||
}
|
||||
|
||||
void TracePlot::on_selectNextPrecharge()
|
||||
{
|
||||
navigator->selectNextPrecharge();
|
||||
}
|
||||
|
||||
void TracePlot::on_colorGroupingPhase()
|
||||
{
|
||||
drawingProperties.colorGrouping = ColorGrouping::PhaseType;
|
||||
Q_EMIT(colorGroupingChanged(ColorGrouping::PhaseType));
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::on_colorGroupingTransaction()
|
||||
{
|
||||
drawingProperties.colorGrouping = ColorGrouping::Transaction;
|
||||
Q_EMIT(colorGroupingChanged(ColorGrouping::Transaction));
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::on_colorGroupingThread()
|
||||
{
|
||||
drawingProperties.colorGrouping = ColorGrouping::Thread;
|
||||
Q_EMIT(colorGroupingChanged(ColorGrouping::Thread));
|
||||
replot();
|
||||
}
|
||||
|
||||
void TracePlot::on_goToTransaction()
|
||||
{
|
||||
bool ok;
|
||||
int maxID = navigator->GeneralTraceInfo().numberOfTransactions;
|
||||
int transactionID = QInputDialog::getInt(this,"Go to transaction","Enter transaction ID (0 - " + QString::number(maxID) + ")",0,0,maxID,1,&ok);
|
||||
if(ok)
|
||||
{
|
||||
navigator->clearSelectedTransactions();
|
||||
navigator->selectTransaction(transactionID);
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::on_goToPhase()
|
||||
{
|
||||
bool ok;
|
||||
int maxID = navigator->GeneralTraceInfo().numberOfPhases;
|
||||
int phaseID = QInputDialog::getInt(this,"Go to phase","Enter phase ID (0 - " + QString::number(maxID) + ")",0,0,maxID,1,&ok);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
navigator->clearSelectedTransactions();
|
||||
navigator->selectTransaction(navigator->TraceFile().getTransactionIDFromPhaseID(phaseID));
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::on_deselectAll()
|
||||
{
|
||||
navigator->clearSelectedTransactions();
|
||||
}
|
||||
|
||||
void TracePlot::on_insertComment()
|
||||
{
|
||||
traceTime time = invTransform(xBottom, contextMenuMouseDown.x());
|
||||
bool ok;
|
||||
QString text = QInputDialog::getText(this,QString("Insert comment"),QString("Insert comment at ") + prettyFormatTime(time),QLineEdit::Normal,QString(),&ok);
|
||||
if(ok)
|
||||
{
|
||||
navigator->insertComment(Comment(time,text));
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::on_goToTime()
|
||||
{
|
||||
double goToTime;
|
||||
GoToTimeDialog dialog(&goToTime,this);
|
||||
int dialogCode = dialog.exec();
|
||||
if(dialogCode == QDialog::Accepted)
|
||||
{
|
||||
traceTime time = static_cast<traceTime>(goToTime)*1000;
|
||||
navigator->navigateToTime(time);
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::on_exportToPDF()
|
||||
{
|
||||
QwtPlotRenderer renderer;
|
||||
QString filename = QFileDialog::getSaveFileName(this, "Export to SVG", "", "Portable Document Format(*.svg)");
|
||||
if(filename != "")
|
||||
{
|
||||
QBrush saved = this->canvasBackground();
|
||||
this->setCanvasBackground(QBrush(Qt::white));
|
||||
renderer.renderDocument(this, filename,"svg", QSizeF(this->widthMM(),this->heightMM()));
|
||||
this->setCanvasBackground(QBrush(saved));
|
||||
}
|
||||
}
|
||||
|
||||
/* Keyboard and mouse events
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
void TracePlot::keyPressEvent(QKeyEvent *keyPressedEvent)
|
||||
{
|
||||
int key = keyPressedEvent->key();
|
||||
if(Qt::Key_Control == key)
|
||||
keyPressData.ctrlPressed = true;
|
||||
else if(Qt::Key_Shift == key)
|
||||
keyPressData.shiftPressed = true;
|
||||
else if(Qt::Key_Right == key)
|
||||
navigator->selectNextTransaction();
|
||||
else if(Qt::Key_Left == key)
|
||||
navigator->selectPreviousTransaction();
|
||||
}
|
||||
|
||||
void TracePlot::keyReleaseEvent(QKeyEvent *keyReleasedEvent)
|
||||
{
|
||||
int key = keyReleasedEvent->key();
|
||||
|
||||
if(Qt::Key_Control == key)
|
||||
keyPressData.ctrlPressed = false;
|
||||
else if(Qt::Key_Shift == key)
|
||||
{
|
||||
keyPressData.shiftPressed = false;
|
||||
exitZoomMode();
|
||||
replot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TracePlot::eventFilter(QObject *object, QEvent *event)
|
||||
{
|
||||
if(object == canvas())
|
||||
{
|
||||
switch(event->type())
|
||||
{
|
||||
case QEvent::Wheel :
|
||||
{
|
||||
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
|
||||
traceTime zoomCenter = static_cast<traceTime>(this->invTransform(xBottom, wheelEvent->x()));
|
||||
|
||||
(wheelEvent->delta() > 0) ? zoomIn(zoomCenter) : zoomOut(zoomCenter);
|
||||
|
||||
return true;
|
||||
}
|
||||
case QEvent::MouseButtonPress:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
|
||||
if(mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
if(keyPressData.shiftPressed)
|
||||
{
|
||||
mouseDownData.zoomSpan.setBegin(alignToClk(invTransform(xBottom, mouseEvent->x()),navigator->GeneralTraceInfo().clkPeriod));
|
||||
mouseDownData.zoomSpan.setEnd(alignToClk(invTransform(xBottom, mouseEvent->x()),navigator->GeneralTraceInfo().clkPeriod));
|
||||
enterZoomMode();
|
||||
}
|
||||
else
|
||||
{
|
||||
mouseDownData.mouseDownX = mouseEvent->x();
|
||||
mouseDownData.mouseDownTime = GetCurrentTimespan().Middle();
|
||||
mouseDownData.mouseIsDownForDragging = true;
|
||||
canvas()->setCursor(Qt::ClosedHandCursor);
|
||||
SelectTransaction(mouseEvent->x(), mouseEvent->y());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else if(mouseEvent->button() == Qt::RightButton)
|
||||
{
|
||||
openContextMenu(this->canvas()->mapToGlobal(mouseEvent->pos()),mouseEvent->pos());
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonRelease:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
|
||||
if(mouseEvent->button() == Qt::LeftButton)
|
||||
{
|
||||
if(mouseDownData.mouseIsDownForDragging)
|
||||
{
|
||||
mouseDownData.mouseIsDownForDragging = false;
|
||||
canvas()->setCursor(Qt::ArrowCursor);
|
||||
return true;
|
||||
}
|
||||
else if(mouseDownData.mouseIsDownForZooming)
|
||||
{
|
||||
exitZoomMode();
|
||||
traceTime newCenter = mouseDownData.zoomSpan.Middle();
|
||||
setZoomLevel(mouseDownData.zoomSpan.timeCovered());
|
||||
navigator->navigateToTime(newCenter);
|
||||
replot();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseMove:
|
||||
{
|
||||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||||
|
||||
if(mouseDownData.mouseIsDownForDragging)
|
||||
{
|
||||
traceTime deltaTime = invTransform(xBottom, mouseDownData.mouseDownX) - invTransform(xBottom, mouseEvent->x());
|
||||
navigator->navigateToTime(mouseDownData.mouseDownTime + deltaTime);
|
||||
return true;
|
||||
}
|
||||
else if(mouseDownData.mouseIsDownForZooming)
|
||||
{
|
||||
mouseDownData.zoomSpan.setEnd(alignToClk(invTransform(xBottom, mouseEvent->x()),navigator->GeneralTraceInfo().clkPeriod));
|
||||
if(mouseDownData.zoomSpan.Begin() < mouseDownData.zoomSpan.End())
|
||||
zoomZone->setInterval(mouseDownData.zoomSpan.Begin(),mouseDownData.zoomSpan.End());
|
||||
else
|
||||
zoomZone->setInterval(mouseDownData.zoomSpan.End(),mouseDownData.zoomSpan.Begin());
|
||||
|
||||
replot();
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TracePlot::SelectTransaction(int x, int y)
|
||||
{
|
||||
double yVal = invTransform(yLeft, y);
|
||||
traceTime time = invTransform(xBottom, x);
|
||||
vector<shared_ptr<Transaction>> selectedTransactions = tracePlotItem->getSelectedTransactions(time,yVal);
|
||||
if(selectedTransactions.size() > 0)
|
||||
{
|
||||
if(!keyPressData.ctrlPressed)
|
||||
navigator->clearSelectedTransactions();
|
||||
navigator->addSelectedTransactions(selectedTransactions);
|
||||
}
|
||||
}
|
||||
|
||||
void TracePlot::openContextMenu(const QPoint& pos,const QPoint& mouseDown)
|
||||
{
|
||||
contextMenuMouseDown = mouseDown;
|
||||
contextMenu->exec(pos);
|
||||
}
|
||||
|
||||
|
||||
151
analyzer/analyzer/presentation/traceplot.h
Normal file
151
analyzer/analyzer/presentation/traceplot.h
Normal file
@@ -0,0 +1,151 @@
|
||||
#ifndef TRACEPLOT_H
|
||||
#define TRACEPLOT_H
|
||||
#include <qwt_plot.h>
|
||||
#include <QString>
|
||||
#include <QColor>
|
||||
#include <qwt_scale_draw.h>
|
||||
#include <vector>
|
||||
#include <qwt_plot_marker.h>
|
||||
#include <QAction>
|
||||
#include <qwt_plot_zoneitem.h>
|
||||
#include "traceplotitem.h"
|
||||
#include "tracenavigator.h"
|
||||
#include "queryeditor.h"
|
||||
|
||||
|
||||
#include "markerplotitem.h"
|
||||
/* A plot that plots all phases and transactions of a trace file
|
||||
* Y Axis : Bank0,...,Bank7,Trans,CC
|
||||
* X Axis : Time
|
||||
*
|
||||
*/
|
||||
|
||||
class TracePlotMouseLabel;
|
||||
|
||||
class TracePlot : public QwtPlot
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TracePlot(QWidget *parent = NULL);
|
||||
void init(TraceNavigator* navigator);
|
||||
Timespan GetCurrentTimespan();
|
||||
traceTime ZoomLevel() const{return zoomLevel;}
|
||||
|
||||
void setUpActions();
|
||||
|
||||
void setUpContextMenu();
|
||||
public Q_SLOTS:
|
||||
void currentTraceTimeChanged();
|
||||
void selectedTransactionsChanged();
|
||||
void commentsChanged();
|
||||
|
||||
|
||||
Q_SIGNALS:
|
||||
void tracePlotZoomChanged();
|
||||
void colorGroupingChanged(ColorGrouping colorgrouping);
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_executeQuery();
|
||||
void on_selectNextRefresh();
|
||||
void on_selectNextActivate();
|
||||
void on_selectNextPrecharge();
|
||||
void on_colorGroupingPhase();
|
||||
void on_colorGroupingTransaction();
|
||||
void on_colorGroupingThread();
|
||||
void on_goToTransaction();
|
||||
void on_goToPhase();
|
||||
void on_deselectAll();
|
||||
void on_insertComment();
|
||||
void on_goToTime();
|
||||
void on_exportToPDF();
|
||||
|
||||
private:
|
||||
bool isInitialized;
|
||||
TraceNavigator* navigator;
|
||||
TraceDrawingProperties drawingProperties;
|
||||
TracePlotItem *tracePlotItem;
|
||||
QwtPlotZoneItem *zoomZone;
|
||||
std::vector<std::shared_ptr<Transaction>> transactions;
|
||||
QueryEditor *queryEditor;
|
||||
QMenu* contextMenu;
|
||||
|
||||
void setUpTracePlotItem();
|
||||
void setUpDrawingProperties();
|
||||
void setUpGrid();
|
||||
void setUpAxis();
|
||||
void setUpZoom();
|
||||
void setUpQueryEditor();
|
||||
void connectNavigatorQ_SIGNALS();
|
||||
|
||||
void getAndDrawComments();
|
||||
|
||||
|
||||
/* zooming
|
||||
*
|
||||
*/
|
||||
traceTime zoomLevel;
|
||||
constexpr static int minZoomClks = 10;
|
||||
constexpr static int maxZoomClks = 2000;
|
||||
constexpr static int GridVisiblityClks = 100;
|
||||
constexpr static int textVisibilityClks = 200;
|
||||
traceTime minZoomLevel,maxZoomLevel, textVisibilityZoomLevel;
|
||||
|
||||
constexpr static double zoomFactor = 0.8;
|
||||
void zoomIn(traceTime zoomCenter);
|
||||
void zoomOut(traceTime zoomCenter);
|
||||
void setZoomLevel(traceTime newZoomLevel);
|
||||
void exitZoomMode();
|
||||
void enterZoomMode();
|
||||
|
||||
|
||||
/* keyboard an mouse events
|
||||
*
|
||||
*/
|
||||
bool eventFilter( QObject *object, QEvent *event );
|
||||
|
||||
QAction* goToTime;
|
||||
QAction* goToTransaction;
|
||||
QAction* goToPhase;
|
||||
QAction* showQueryEditor;
|
||||
QAction* insertComment;
|
||||
QAction* deselectAll;
|
||||
QAction* selectNextRefresh;
|
||||
QAction* selectNextActivate;
|
||||
QAction* selectNextPrecharge;
|
||||
QAction* setColorGroupingPhase;
|
||||
QAction* setColorGroupingTransaction;
|
||||
QAction* setColorGroupingThread;
|
||||
QAction* exportToPdf;
|
||||
|
||||
TracePlotMouseLabel* mouseLabel;
|
||||
|
||||
void openContextMenu(const QPoint& pos,const QPoint& mouseDown);
|
||||
QPoint contextMenuMouseDown;
|
||||
void SelectTransaction(int x, int y);
|
||||
void keyPressEvent(QKeyEvent *keyPressedEvent);
|
||||
void keyReleaseEvent(QKeyEvent *keyReleasedEvent);
|
||||
|
||||
struct KeyPressData
|
||||
{
|
||||
bool ctrlPressed, shiftPressed;
|
||||
KeyPressData():ctrlPressed(false),shiftPressed(false){}
|
||||
};
|
||||
|
||||
struct MouseDownData
|
||||
{
|
||||
traceTime mouseDownTime;
|
||||
Timespan zoomSpan;
|
||||
int mouseDownX;
|
||||
bool mouseIsDownForDragging;
|
||||
bool mouseIsDownForZooming;
|
||||
MouseDownData(): mouseDownTime(0),mouseDownX(0),mouseIsDownForDragging(false),mouseIsDownForZooming(false){}
|
||||
};
|
||||
|
||||
MouseDownData mouseDownData;
|
||||
KeyPressData keyPressData;
|
||||
};
|
||||
|
||||
|
||||
#endif // TRACEPLOT_H
|
||||
36
analyzer/analyzer/presentation/traceplotitem.cpp
Normal file
36
analyzer/analyzer/presentation/traceplotitem.cpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#include "traceplotitem.h"
|
||||
#include "tracedrawing.h"
|
||||
#include "util/colorgenerator.h"
|
||||
#include <qwt_painter.h>
|
||||
#include <QRect>
|
||||
#include <qwt_scale_map.h>
|
||||
#include <tuple>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
int TracePlotItem::rtti() const
|
||||
{
|
||||
return QwtPlotItem::Rtti_PlotUserItem;
|
||||
}
|
||||
|
||||
void TracePlotItem::draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const
|
||||
{
|
||||
for(const auto &transaction : transactions)
|
||||
{
|
||||
bool highlight = navigator.transactionIsSelected(transaction);
|
||||
transaction->draw(painter,xMap,yMap,canvasRect,highlight,drawingProperties);
|
||||
}
|
||||
}
|
||||
|
||||
vector<shared_ptr<Transaction>> TracePlotItem::getSelectedTransactions(traceTime time, double yVal)
|
||||
{
|
||||
vector<shared_ptr<Transaction>> result;
|
||||
|
||||
for(const auto &transaction : transactions)
|
||||
{
|
||||
if(transaction->isSelected(time,yVal,drawingProperties))
|
||||
result.push_back(transaction);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
32
analyzer/analyzer/presentation/traceplotitem.h
Normal file
32
analyzer/analyzer/presentation/traceplotitem.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef TRACEPLOTITEM_H
|
||||
#define TRACEPLOTITEM_H
|
||||
|
||||
#include <qwt_plot_item.h>
|
||||
#include <QColor>
|
||||
#include <QPoint>
|
||||
#include <vector>
|
||||
#include "businessObjects/tracetime.h"
|
||||
#include "businessObjects/transaction.h"
|
||||
#include "presentation/tracedrawingproperties.h"
|
||||
#include "util/colorgenerator.h"
|
||||
#include "presentation/tracenavigator.h"
|
||||
|
||||
class TracePlotItem : public QwtPlotItem
|
||||
{
|
||||
private:
|
||||
const std::vector<std::shared_ptr<Transaction>> &transactions;
|
||||
const TraceNavigator& navigator;
|
||||
const TraceDrawingProperties &drawingProperties;
|
||||
|
||||
public:
|
||||
TracePlotItem(const std::vector<std::shared_ptr<Transaction>> &transactions,const TraceNavigator& navigator, const TraceDrawingProperties &drawingProperties):
|
||||
transactions(transactions),navigator(navigator),drawingProperties(drawingProperties){}
|
||||
|
||||
virtual int rtti() const;
|
||||
virtual void draw(QPainter *painter, const QwtScaleMap &xMap, const QwtScaleMap &yMap, const QRectF &canvasRect) const;
|
||||
std::vector<std::shared_ptr<Transaction>> getSelectedTransactions(traceTime time,double yVal);
|
||||
|
||||
};
|
||||
|
||||
#endif // TRACEPLOTITEM_H
|
||||
|
||||
46
analyzer/analyzer/presentation/tracetesttreewidget.cpp
Normal file
46
analyzer/analyzer/presentation/tracetesttreewidget.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "tracetesttreewidget.h"
|
||||
|
||||
TraceTestTreeWidget::TraceTestTreeWidget(QWidget *parent) : QTreeWidget(parent)
|
||||
{
|
||||
QObject::connect(this,SIGNAL(itemSelectionChanged()),this,SLOT(itemSelectionChanged()));
|
||||
setHeaderHidden(true);
|
||||
}
|
||||
|
||||
void TraceTestTreeWidget::addTraceTestResult(const TraceTestResults &traceTestResult)
|
||||
{
|
||||
|
||||
QTreeWidgetItem* top = new QTreeWidgetItem({traceTestResult.getTraceName()});
|
||||
addTopLevelItem(top);
|
||||
|
||||
if(traceTestResult.hasPassedAllTests())
|
||||
top->setTextColor(0,Qt::green);
|
||||
else
|
||||
top->setTextColor(0,Qt::red);
|
||||
|
||||
for(const TestResult& testResult: traceTestResult.getTestResults())
|
||||
{
|
||||
new TestResultTreeItem(top, testResult);
|
||||
}
|
||||
}
|
||||
|
||||
void TraceTestTreeWidget::itemSelectionChanged()
|
||||
{
|
||||
if(!selectedItems().isEmpty() && selectedItems().at(0)->type() == TestResultTreeItem::testResultTreeItemType)
|
||||
{
|
||||
TestResultTreeItem* testResultItem = static_cast<TestResultTreeItem*>(selectedItems().at(0));
|
||||
Q_EMIT setMessage(testResultItem->getMessage());
|
||||
}
|
||||
else
|
||||
{
|
||||
setMessage(QString(""));
|
||||
}
|
||||
}
|
||||
|
||||
TraceTestTreeWidget::TestResultTreeItem::TestResultTreeItem(QTreeWidgetItem *parent, const TestResult& testResult)
|
||||
:QTreeWidgetItem(parent,testResultTreeItemType)
|
||||
{
|
||||
setText(0, testResult.getTestName());
|
||||
if(!testResult.hasPassed())
|
||||
setTextColor(0,Qt::red);
|
||||
message = testResult.getMessage();
|
||||
}
|
||||
31
analyzer/analyzer/presentation/tracetesttreewidget.h
Normal file
31
analyzer/analyzer/presentation/tracetesttreewidget.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef TRACETESTTREEWIDGET_H
|
||||
#define TRACETESTTREEWIDGET_H
|
||||
#include <QTreeWidget>
|
||||
#include <businessObjects/tracetestresults.h>
|
||||
|
||||
class TraceTestTreeWidget: public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TraceTestTreeWidget(QWidget *parent = 0);
|
||||
void addTraceTestResult(const TraceTestResults& traceTestResult);
|
||||
|
||||
Q_SIGNALS:
|
||||
void setMessage(QString message);
|
||||
|
||||
private:
|
||||
class TestResultTreeItem : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
TestResultTreeItem(QTreeWidgetItem *parent, const TestResult& testResult);
|
||||
static constexpr int testResultTreeItemType = 1002;
|
||||
QString getMessage(){return message;}
|
||||
private:
|
||||
QString message;
|
||||
};
|
||||
|
||||
private Q_SLOTS:
|
||||
void itemSelectionChanged();
|
||||
};
|
||||
|
||||
#endif // TRACETESTTREEWIDGET_H
|
||||
94
analyzer/analyzer/presentation/transactiontreewidget.cpp
Normal file
94
analyzer/analyzer/presentation/transactiontreewidget.cpp
Normal file
@@ -0,0 +1,94 @@
|
||||
#include "transactiontreewidget.h"
|
||||
#include "data/tracedb.h"
|
||||
#include <QHeaderView>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
|
||||
TransactionTreeWidget::TransactionTreeWidget(QWidget *parent) : QTreeWidget(parent), isInitialized(false)
|
||||
{
|
||||
QObject::connect(this,SIGNAL(customContextMenuRequested(QPoint)),this,SLOT(ContextMenuRequested(QPoint)));
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
goToTransaction = new QAction("Move to",this);
|
||||
}
|
||||
|
||||
void TransactionTreeWidget::init(TraceNavigator *navigator)
|
||||
{
|
||||
Q_ASSERT(isInitialized == false);
|
||||
isInitialized = true;
|
||||
|
||||
this->navigator = navigator;
|
||||
setColumnCount(3);
|
||||
setHeaderLabels(QStringList({"Transaction", "Value", "Value"}));
|
||||
}
|
||||
|
||||
void TransactionTreeWidget::AppendTransaction(const shared_ptr<Transaction> &transaction)
|
||||
{
|
||||
QTreeWidgetItem *node = new TransactionTreeItem(this,transaction);
|
||||
addTopLevelItem(node);
|
||||
}
|
||||
|
||||
|
||||
void TransactionTreeWidget::ContextMenuRequested(QPoint point)
|
||||
{
|
||||
if(selectedItems().count() > 0 && selectedItems().at(0)->type() == TransactionTreeWidget::TransactionTreeItem::transactionTreeItemType)
|
||||
{
|
||||
QMenu contextMenu;
|
||||
contextMenu.addActions({goToTransaction});
|
||||
QAction* selectedContextMenuItems = contextMenu.exec(mapToGlobal(point));
|
||||
|
||||
if(selectedContextMenuItems)
|
||||
{
|
||||
TransactionTreeItem *item = static_cast<TransactionTreeItem*>(selectedItems().at(0));
|
||||
navigator->selectTransaction(item->Id());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TransactionTreeWidget::TransactionTreeItem::TransactionTreeItem(QTreeWidget *parent, const shared_ptr<Transaction> &transaction) : QTreeWidgetItem(parent,transactionTreeItemType)
|
||||
{
|
||||
this->setText(0, QString::number(transaction->Id()));
|
||||
this->id = transaction->Id();
|
||||
|
||||
QTreeWidgetItem *time = new QTreeWidgetItem({"Timespan"});
|
||||
AppendTimespan(time, transaction->Span());
|
||||
this->addChild(time);
|
||||
this->addChild(new QTreeWidgetItem( {"Lenght", prettyFormatTime(transaction->Span().timeCovered())}));
|
||||
|
||||
this->addChild(new QTreeWidgetItem( {"Channel", QString::number(transaction->Channel())}));
|
||||
this->addChild(new QTreeWidgetItem( {"Bank", QString::number(transaction->Bank())} ));
|
||||
this->addChild(new QTreeWidgetItem( {"Bankgroup", QString::number(transaction->BankGroup())} ));
|
||||
this->addChild(new QTreeWidgetItem( {"Row", QString::number(transaction->Row())} ));
|
||||
this->addChild(new QTreeWidgetItem( {"Column", QString::number(transaction->Column())} ));
|
||||
this->addChild(new QTreeWidgetItem( {"Address", QString("0x") + QString::number(transaction->Address(),16)} ));
|
||||
|
||||
if(!transaction->isControllerInternal())
|
||||
{
|
||||
this->addChild(new QTreeWidgetItem( {"Burstlength", QString::number(transaction->Burstlength())}));
|
||||
this->addChild(new QTreeWidgetItem( {"Thread", QString::number(transaction->Thread())}));
|
||||
}
|
||||
|
||||
QTreeWidgetItem *phasesNode = new QTreeWidgetItem(this);
|
||||
phasesNode->setText(0,"Phases");
|
||||
phasesNode->addChild(new QTreeWidgetItem( {"", "Begin", "End"} ));
|
||||
|
||||
for(std::shared_ptr<Phase> phase : transaction->Phases())
|
||||
{
|
||||
AppendPhase(phasesNode, *phase);
|
||||
}
|
||||
}
|
||||
|
||||
void TransactionTreeWidget::TransactionTreeItem::AppendPhase(QTreeWidgetItem *parent, const Phase &phase)
|
||||
{
|
||||
QTreeWidgetItem *node = new QTreeWidgetItem(parent);
|
||||
node->setText(0, phase.Name() + QString(" [") + QString::number(phase.Id()) + QString("]"));
|
||||
|
||||
AppendTimespan(node, phase.Span());
|
||||
}
|
||||
|
||||
void TransactionTreeWidget::TransactionTreeItem::AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan)
|
||||
{
|
||||
parent->setText(1, prettyFormatTime(timespan.Begin()));
|
||||
parent->setText(2, prettyFormatTime(timespan.End()));
|
||||
}
|
||||
48
analyzer/analyzer/presentation/transactiontreewidget.h
Normal file
48
analyzer/analyzer/presentation/transactiontreewidget.h
Normal file
@@ -0,0 +1,48 @@
|
||||
#ifndef TRANSACTIONTREEWIDGET_H
|
||||
#define TRANSACTIONTREEWIDGET_H
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include "tracenavigator.h"
|
||||
#include <iostream>
|
||||
#include <QMenu>
|
||||
|
||||
class TransactionTreeWidget : public QTreeWidget
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TransactionTreeWidget(QWidget *parent);
|
||||
|
||||
void AppendTransaction(const std::shared_ptr<Transaction> &transaction);
|
||||
virtual void init(TraceNavigator *navigator);
|
||||
|
||||
public Q_SLOTS:
|
||||
void ContextMenuRequested(QPoint point);
|
||||
|
||||
protected:
|
||||
TraceNavigator *navigator;
|
||||
|
||||
private:
|
||||
bool isInitialized;
|
||||
void AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan);
|
||||
void AppendPhase(QTreeWidgetItem *parent, const Phase &phase);
|
||||
QAction* goToTransaction;
|
||||
|
||||
class TransactionTreeItem : public QTreeWidgetItem
|
||||
{
|
||||
public:
|
||||
static constexpr int transactionTreeItemType = 1001;
|
||||
TransactionTreeItem(QTreeWidget *parent, const std::shared_ptr<Transaction> &trans);
|
||||
ID Id(){return id;}
|
||||
private:
|
||||
ID id;
|
||||
void AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan);
|
||||
void AppendPhase(QTreeWidgetItem *parent, const Phase &phase);
|
||||
};
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // TRANSACTIONTREEWIDGET_H
|
||||
29
analyzer/analyzer/presentation/util/clkgrid.cpp
Normal file
29
analyzer/analyzer/presentation/util/clkgrid.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include "clkgrid.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
void ClkGrid::updateScaleDiv(const QwtScaleDiv &xMap, const QwtScaleDiv &yMap)
|
||||
{
|
||||
QwtScaleDiv scaleDiv;
|
||||
scaleDiv.setInterval( xMap.interval() );
|
||||
|
||||
double min = xMap.interval().minValue();
|
||||
double max = xMap.interval().maxValue();
|
||||
|
||||
if ( min > max )
|
||||
qSwap( min, max );
|
||||
|
||||
if((max - min) < maxVisibility)
|
||||
{
|
||||
min = static_cast<long long>( min / clkPeriod ) * clkPeriod;
|
||||
QList<double > ticks;
|
||||
for ( double tick = min; tick <= max; tick += clkPeriod )
|
||||
ticks += tick;
|
||||
|
||||
scaleDiv.setTicks( QwtScaleDiv::MajorTick, ticks );
|
||||
|
||||
}
|
||||
|
||||
QwtPlotGrid::updateScaleDiv( scaleDiv, yMap );
|
||||
}
|
||||
18
analyzer/analyzer/presentation/util/clkgrid.h
Normal file
18
analyzer/analyzer/presentation/util/clkgrid.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CLKGRID_H
|
||||
#define CLKGRID_H
|
||||
|
||||
#include <qwt_plot_grid.h>
|
||||
#include "businessObjects/tracetime.h"
|
||||
|
||||
class ClkGrid : public QwtPlotGrid
|
||||
{
|
||||
public:
|
||||
virtual void updateScaleDiv(const QwtScaleDiv &xMap, const QwtScaleDiv &yMap);
|
||||
ClkGrid(unsigned int clkPeriod, traceTime maxVisibility) : clkPeriod(clkPeriod), maxVisibility(maxVisibility){}
|
||||
|
||||
private:
|
||||
unsigned int clkPeriod;
|
||||
double maxVisibility;
|
||||
};
|
||||
|
||||
#endif // CLKGRID_H
|
||||
31
analyzer/analyzer/presentation/util/colorgenerator.cpp
Normal file
31
analyzer/analyzer/presentation/util/colorgenerator.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "colorgenerator.h"
|
||||
#include <exception>
|
||||
ColorGenerator::ColorGenerator()
|
||||
{
|
||||
r[0] = 0xFF; r[1] = 0x00; r[2] = 0x00; r[3] = 0xFF;
|
||||
g[0] = 0x00; g[1] = 0xFF; g[2] = 0x00; g[3] = 0xFF;
|
||||
b[0] = 0x00; b[1] = 0x00; b[2] = 0xFF; b[3] = 0x00;
|
||||
|
||||
r[4] = 0xFF; r[5] = 0x00; r[6] = 0xFF; r[7] = 0x6B;
|
||||
g[4] = 0x00; g[5] = 0xFF; g[6] = 0xA5; g[7] = 0x8E;
|
||||
b[4] = 0xFF; b[5] = 0xFF; b[6] = 0x00; b[7] = 0x23;
|
||||
|
||||
r[8] = 0x8A; r[9] = 0xFF; r[10] = 0x7C; r[11] = 0x00;
|
||||
g[8] = 0x2B; g[9] = 0xD7; g[10] = 0xFC; g[11] = 0x00;
|
||||
b[8] = 0xE2; b[9] = 0x00; b[10] = 0x00; b[11] = 0x80;
|
||||
|
||||
r[12] = 0x80; r[13] = 0x00; r[14] = 0xEE; r[15] = 0xFF;
|
||||
g[12] = 0x00; g[13] = 0x80; g[14] = 0x82; g[15] = 0x45;
|
||||
b[12] = 0x00; b[13] = 0x00; b[14] = 0xEE; b[15] = 0x00;
|
||||
|
||||
}
|
||||
|
||||
QColor ColorGenerator::getColor(unsigned int i)
|
||||
{
|
||||
static ColorGenerator gen;
|
||||
i = i % 16;
|
||||
QColor result(gen.r[i],gen.g[i],gen.b[i]);
|
||||
result.setAlpha(130);
|
||||
return result;
|
||||
}
|
||||
|
||||
21
analyzer/analyzer/presentation/util/colorgenerator.h
Normal file
21
analyzer/analyzer/presentation/util/colorgenerator.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef COLORGENERATOR_H
|
||||
#define COLORGENERATOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <QColor>
|
||||
|
||||
class ColorGenerator
|
||||
{
|
||||
private:
|
||||
static constexpr int NumberOfColors = 16;
|
||||
int r[NumberOfColors];
|
||||
int g[NumberOfColors];
|
||||
int b[NumberOfColors];
|
||||
ColorGenerator();
|
||||
|
||||
public:
|
||||
static QColor getColor(unsigned int i);
|
||||
};
|
||||
|
||||
|
||||
#endif // RANDOMCOLORGENERATOR_H
|
||||
20
analyzer/analyzer/presentation/util/customlabelscaledraw.h
Normal file
20
analyzer/analyzer/presentation/util/customlabelscaledraw.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CUSTOMLABELSCALEDRAW_H
|
||||
#define CUSTOMLABELSCALEDRAW_H
|
||||
#include <qwt_text.h>
|
||||
#include <qwt_scale_draw.h>
|
||||
#include <QHash>
|
||||
|
||||
class CustomLabelScaleDraw : public QwtScaleDraw
|
||||
{
|
||||
private:
|
||||
QHash<int,QString> labels;
|
||||
|
||||
public:
|
||||
CustomLabelScaleDraw(QHash<int,QString> labels): labels(labels){}
|
||||
virtual QwtText label(double v) const
|
||||
{
|
||||
return QwtText(labels[static_cast<int>(v)]);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // CUSTOMLABELSCALEDRAW_H
|
||||
16
analyzer/analyzer/presentation/util/engineeringScaleDraw.h
Normal file
16
analyzer/analyzer/presentation/util/engineeringScaleDraw.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef ENGINEERINGSCALEDRAW_H
|
||||
#define ENGINEERINGSCALEDRAW_H
|
||||
#include <qwt_scale_draw.h>
|
||||
#include <QString>
|
||||
#include "thirdParty/eng_format.h"
|
||||
#include "businessObjects/tracetime.h"
|
||||
|
||||
class EngineeringScaleDraw : public QwtScaleDraw
|
||||
{
|
||||
public:
|
||||
virtual QwtText label(double number) const
|
||||
{
|
||||
return QwtText(QString::number(number/1000,'g',9));
|
||||
}
|
||||
};
|
||||
#endif // ENGINEERINGSCALEDRAW_H
|
||||
33
analyzer/analyzer/presentation/util/testlight.cpp
Normal file
33
analyzer/analyzer/presentation/util/testlight.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "testlight.h"
|
||||
#include <QPainter>
|
||||
|
||||
TestLight::TestLight(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
setGray();
|
||||
}
|
||||
|
||||
void TestLight::setGray()
|
||||
{
|
||||
lightColor = QColor(Qt::gray);
|
||||
update();
|
||||
}
|
||||
|
||||
void TestLight::setGreen()
|
||||
{
|
||||
lightColor = QColor(Qt::green);
|
||||
update();
|
||||
}
|
||||
|
||||
void TestLight::setRed()
|
||||
{
|
||||
lightColor = QColor(Qt::red);
|
||||
update();
|
||||
}
|
||||
|
||||
void TestLight::paintEvent(QPaintEvent* /*paintEvent*/)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.fillRect(this->rect(),lightColor);
|
||||
painter.drawRect(this->rect());
|
||||
}
|
||||
|
||||
23
analyzer/analyzer/presentation/util/testlight.h
Normal file
23
analyzer/analyzer/presentation/util/testlight.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef TESTLIGHT_H
|
||||
#define TESTLIGHT_H
|
||||
#include <QWidget>
|
||||
#include <QColor>
|
||||
#include <QPaintEvent>
|
||||
|
||||
class TestLight : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TestLight(QWidget *parent = 0);
|
||||
void setGreen();
|
||||
void setRed();
|
||||
void setGray();
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *paintEvent);
|
||||
|
||||
private:
|
||||
QColor lightColor;
|
||||
};
|
||||
|
||||
#endif // TESTLIGHT_H
|
||||
40
analyzer/analyzer/queryeditor.cpp
Normal file
40
analyzer/analyzer/queryeditor.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "queryeditor.h"
|
||||
#include "ui_queryeditor.h"
|
||||
#include <QMessageBox>
|
||||
#include <vector>
|
||||
|
||||
QueryEditor::QueryEditor(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::QueryEditor)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->queryHead->setText(queryTexts.queryHead);
|
||||
}
|
||||
|
||||
QueryEditor::~QueryEditor()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void QueryEditor::init(TraceNavigator *navigator)
|
||||
{
|
||||
this->navigator = navigator;
|
||||
ui->transactiontreeWidget->init(navigator);
|
||||
}
|
||||
|
||||
void QueryEditor::on_executeQuery_clicked()
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<std::shared_ptr<Transaction>> result = navigator->TraceFile().getTransactionsWithCustomQuery(queryTexts.queryHead + " " + ui->queryEdit->toPlainText());
|
||||
ui->transactiontreeWidget->clear();
|
||||
for(const auto & trans : result)
|
||||
{
|
||||
ui->transactiontreeWidget->AppendTransaction(trans);
|
||||
}
|
||||
}
|
||||
catch(sqlException ex)
|
||||
{
|
||||
QMessageBox::warning(this,"Query failed",ex.what());
|
||||
}
|
||||
}
|
||||
30
analyzer/analyzer/queryeditor.h
Normal file
30
analyzer/analyzer/queryeditor.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef QUERYEDITOR_H
|
||||
#define QUERYEDITOR_H
|
||||
|
||||
#include <QWidget>
|
||||
#include "data/QueryTexts.h"
|
||||
#include "presentation/tracenavigator.h"
|
||||
|
||||
namespace Ui {
|
||||
class QueryEditor;
|
||||
}
|
||||
|
||||
class QueryEditor : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QueryEditor(QWidget *parent = 0);
|
||||
~QueryEditor();
|
||||
void init(TraceNavigator *navigator);
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_executeQuery_clicked();
|
||||
|
||||
private:
|
||||
Ui::QueryEditor *ui;
|
||||
TraceNavigator* navigator;
|
||||
TransactionQueryTexts queryTexts;
|
||||
};
|
||||
|
||||
#endif // QUERYEDITOR_H
|
||||
80
analyzer/analyzer/queryeditor.ui
Normal file
80
analyzer/analyzer/queryeditor.ui
Normal file
@@ -0,0 +1,80 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QueryEditor</class>
|
||||
<widget class="QWidget" name="QueryEditor">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>667</width>
|
||||
<height>451</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTextEdit" name="queryHead">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextEdit" name="queryEdit">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="executeQuery">
|
||||
<property name="text">
|
||||
<string>Execute query</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="TransactionTreeWidget" name="transactiontreeWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>5</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TransactionTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/transactiontreewidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
33
analyzer/analyzer/schedulerwrapper.h
Normal file
33
analyzer/analyzer/schedulerwrapper.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef SCHEDULERWRAPPER_H
|
||||
#define SCHEDULERWRAPPER_H
|
||||
|
||||
#include <tlm.h>
|
||||
#include <systemc.h>
|
||||
#include <tlm_utils/simple_target_socket.h>
|
||||
#include <tlm_utils/simple_initiator_socket.h>
|
||||
#include <tlm_utils/peq_with_cb_and_phase.h>
|
||||
|
||||
struct SchedulerWrapper : public sc_module
|
||||
{
|
||||
tlm_utils::simple_initiator_socket<SchedulerWrapper> iSocket;
|
||||
tlm_utils::simple_target_socket<SchedulerWrapper> tSocket;
|
||||
|
||||
SC_HAS_PROCESS(SchedulerWrapper);
|
||||
|
||||
SchedulerWrapper(sc_module_name name);
|
||||
|
||||
private:
|
||||
tlm_utils::peq_with_cb_and_phase<SchedulerWrapper> payloadEventQueue;
|
||||
|
||||
tlm::tlm_sync_enum nb_transport_bw(tlm::tlm_generic_payload& payload,tlm::tlm_phase& phase,sc_time& bwDelay);
|
||||
tlm::tlm_sync_enum nb_transport_fw(tlm::tlm_generic_payload& payload,tlm::tlm_phase& phase,sc_time& fwDelay);
|
||||
|
||||
void peqCallback(tlm::tlm_generic_payload& payload,const tlm::tlm_phase& phase);
|
||||
void sendToTarget(tlm::tlm_generic_payload& payload,const tlm::tlm_phase& phase,const sc_time& delay);
|
||||
void sendToInitiator(tlm::tlm_generic_payload& payload,const tlm::tlm_phase& phase,const sc_time& delay);
|
||||
|
||||
};
|
||||
|
||||
#endif // SCHEDULERWRAPPER_H
|
||||
|
||||
|
||||
262
analyzer/analyzer/thirdParty/eng_formant.cpp
vendored
Normal file
262
analyzer/analyzer/thirdParty/eng_formant.cpp
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
// Copyright (C) 2005-2009 by Jukka Korpela
|
||||
// Copyright (C) 2009-2013 by David Hoerl
|
||||
// Copyright (C) 2013 by Martin Moene
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include "eng_format.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/*
|
||||
* Note: using fabs() and other math functions in global namespace for
|
||||
* best compiler coverage.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Note: micro, µ, may not work everywhere, so you can define a glyph yourself:
|
||||
*/
|
||||
#ifndef ENG_FORMAT_MICRO_GLYPH
|
||||
# define ENG_FORMAT_MICRO_GLYPH "µ"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note: if not using signed at the computation of prefix_end below,
|
||||
* VC2010 -Wall issues a warning about unsigned and addition overflow.
|
||||
* Hence the cast to signed int here.
|
||||
*/
|
||||
#define ENG_FORMAT_DIMENSION_OF(a) ( static_cast<int>( sizeof(a) / sizeof(0[a]) ) )
|
||||
|
||||
eng_prefixed_t eng_prefixed;
|
||||
eng_exponential_t eng_exponential;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
char const * const prefixes[/*exp*/][2][9] =
|
||||
{
|
||||
{
|
||||
{ "", "m", ENG_FORMAT_MICRO_GLYPH
|
||||
, "n", "p", "f", "a", "z", "y", },
|
||||
{ "", "k", "M", "G", "T", "P", "E", "Z", "Y", },
|
||||
},
|
||||
{
|
||||
{ "e0", "e-3", "e-6", "e-9", "e-12", "e-15", "e-18", "e-21", "e-24", },
|
||||
{ "e0", "e3", "e6", "e9", "e12", "e15", "e18", "e21", "e24", },
|
||||
},
|
||||
};
|
||||
|
||||
const int prefix_count = ENG_FORMAT_DIMENSION_OF( prefixes[false][false] );
|
||||
|
||||
#if defined( _MSC_VER )
|
||||
|
||||
template <typename T>
|
||||
long lrint( T const x )
|
||||
{
|
||||
return static_cast<long>( x );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int sign( int const value )
|
||||
{
|
||||
return value == 0 ? +1 : value / abs( value );
|
||||
}
|
||||
|
||||
bool is_zero( double const value )
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
return FP_ZERO == fpclassify( value );
|
||||
#else
|
||||
// deliberately compare literally:
|
||||
return 0.0 == value;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_nan( double const value )
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
return isnan( value );
|
||||
#else
|
||||
// deliberately return false for now:
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_inf( double const value )
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
return isinf( value );
|
||||
#else
|
||||
// deliberately return false for now:
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
long degree_of( double const value )
|
||||
{
|
||||
return is_zero( value ) ? 0 : lrint( floor( log10( fabs( value ) ) / 3) );
|
||||
}
|
||||
|
||||
int precision( double const scaled, int const digits )
|
||||
{
|
||||
// MSVC6 requires -2 * DBL_EPSILON;
|
||||
// g++ 4.8.1: ok with -1 * DBL_EPSILON
|
||||
|
||||
return is_zero( scaled ) ? digits - 1 : digits - log10( fabs( scaled ) ) - 2 * DBL_EPSILON;
|
||||
}
|
||||
|
||||
std::string prefix_or_exponent( bool const exponential, int const degree )
|
||||
{
|
||||
return std::string( exponential || 0 == degree ? "" : " " ) + prefixes[ exponential ][ sign(degree) > 0 ][ abs( degree ) ];
|
||||
}
|
||||
|
||||
std::string exponent( int const degree )
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "e" << 3 * degree;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/*
|
||||
* engineering to exponent notation conversion.
|
||||
*/
|
||||
std::string engineering_to_exponent( std::string text );
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
/**
|
||||
* convert real number to prefixed or exponential notation, optionally followed by a unit.
|
||||
*/
|
||||
std::string
|
||||
to_engineering_string( double const value, int const digits, bool exponential, std::string const unit /*= ""*/ )
|
||||
{
|
||||
if ( is_nan( value ) ) return "NaN";
|
||||
else if ( is_inf( value ) ) return "INFINITE";
|
||||
|
||||
const int degree = degree_of( value );
|
||||
|
||||
std::string factor;
|
||||
|
||||
if ( abs( degree ) < prefix_count )
|
||||
{
|
||||
factor = prefix_or_exponent( exponential, degree );
|
||||
}
|
||||
else
|
||||
{
|
||||
exponential = true;
|
||||
factor = exponent( degree );
|
||||
}
|
||||
|
||||
std::ostringstream os;
|
||||
|
||||
const double scaled = value * pow( 1000.0, -degree );
|
||||
|
||||
const std::string space = ( 0 == degree || exponential ) && unit.length() ? " ":"";
|
||||
|
||||
os << std::fixed << std::setprecision( precision( scaled, digits ) ) << scaled << factor << space << unit;
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* convert the output of to_engineering_string() into a double.
|
||||
*/
|
||||
double from_engineering_string( std::string const text )
|
||||
{
|
||||
return strtod( engineering_to_exponent( text ).c_str(), NULL );
|
||||
}
|
||||
|
||||
/**
|
||||
* step a value by the smallest possible increment.
|
||||
*/
|
||||
std::string step_engineering_string( std::string const text, int digits, bool const exponential, bool const positive )
|
||||
{
|
||||
const double value = from_engineering_string( text );
|
||||
|
||||
if ( digits < 3 )
|
||||
{
|
||||
digits = 3;
|
||||
}
|
||||
|
||||
// correctly round to desired precision
|
||||
const int expof10 = is_zero(value) ? 0 : lrint( floor( log10( value ) ) );
|
||||
const int power = expof10 + 1 - digits;
|
||||
|
||||
const double inc = pow( 10.0, power ) * ( positive ? +1 : -1 );
|
||||
const double ret = value + inc;
|
||||
|
||||
return to_engineering_string( ret, digits, exponential );
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
/*
|
||||
* "k" => "1e3"
|
||||
*/
|
||||
std::string prefix_to_exponent( std::string const pfx )
|
||||
{
|
||||
for ( int i = 0; i < 2; ++i )
|
||||
{
|
||||
for( int k = 0; k < prefix_count; ++k )
|
||||
{
|
||||
if ( pfx == prefixes[0][i][k] )
|
||||
{
|
||||
return prefixes[1][i][k] ;
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert engineering presentation to presentation with exponent.
|
||||
*
|
||||
* The engineering presentation should not contain a unit, as the first letter
|
||||
* is interpreted as an SI prefix, e.g. "1 T" is 1e12, not 1 (Tesla).
|
||||
*
|
||||
* "1.23 M" => 1.23e+6
|
||||
* "1.23 kPa" => 1.23e+3 (ok, but not recommended)
|
||||
* "1.23 Pa" => 1.23e+12 (not what's intended!)
|
||||
*/
|
||||
std::string engineering_to_exponent( std::string const text )
|
||||
{
|
||||
std::string::size_type pos = text.find( ' ' );
|
||||
|
||||
if ( std::string::npos == pos )
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
const std::string magnitude = text.substr( 0, pos );
|
||||
const std::string prefix = text.substr( pos + 1, 1 );
|
||||
|
||||
return magnitude + prefix_to_exponent( prefix );
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
// end of file
|
||||
115
analyzer/analyzer/thirdParty/eng_format.h
vendored
Normal file
115
analyzer/analyzer/thirdParty/eng_format.h
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2005-2009 by Jukka Korpela
|
||||
// Copyright (C) 2009-2013 by David Hoerl
|
||||
// Copyright (C) 2013 by Martin Moene
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef ENG_FORMAT_H_INCLUDED
|
||||
#define ENG_FORMAT_H_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* convert a double to the specified number of digits in SI (prefix) or
|
||||
* exponential notation, optionally followed by a unit.
|
||||
*/
|
||||
std::string
|
||||
to_engineering_string( double value, int digits, bool exponential, std::string unit = "" );
|
||||
|
||||
/**
|
||||
* convert the output of to_engineering_string() into a double.
|
||||
*/
|
||||
double
|
||||
from_engineering_string( std::string text );
|
||||
|
||||
/**
|
||||
* step a value by the smallest possible increment.
|
||||
*/
|
||||
std::string
|
||||
step_engineering_string( std::string text, int digits, bool exponential, bool increment );
|
||||
|
||||
//
|
||||
// Extended interface:
|
||||
//
|
||||
|
||||
/**
|
||||
* \var eng_prefixed
|
||||
* \brief select SI (prefix) presentation: to_engineering_string(), step_engineering_string().
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var eng_exponential
|
||||
* \brief select exponential presentation: to_engineering_string(), step_engineering_string().
|
||||
*/
|
||||
|
||||
extern struct eng_prefixed_t {} eng_prefixed;
|
||||
extern struct eng_exponential_t {} eng_exponential;
|
||||
|
||||
/**
|
||||
* \var eng_increment
|
||||
* \brief let step_engineering_string() make a postive step.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \var eng_decrement
|
||||
* \brief let step_engineering_string() make a negative step.
|
||||
*/
|
||||
|
||||
const bool eng_increment = true;
|
||||
const bool eng_decrement = false;
|
||||
|
||||
/**
|
||||
* convert a double to the specified number of digits in SI (prefix) notation,
|
||||
* optionally followed by a unit.
|
||||
*/
|
||||
inline std::string
|
||||
to_engineering_string( double value, int digits, eng_prefixed_t, std::string unit = "" )
|
||||
{
|
||||
return to_engineering_string( value, digits, false, unit );
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a double to the specified number of digits in exponential notation,
|
||||
* optionally followed by a unit.
|
||||
*/
|
||||
inline std::string
|
||||
to_engineering_string( double value, int digits, eng_exponential_t, std::string unit = "" )
|
||||
{
|
||||
return to_engineering_string( value, digits, true, unit );
|
||||
}
|
||||
|
||||
/**
|
||||
* step a value by the smallest possible increment, using SI notation.
|
||||
*/
|
||||
inline std::string
|
||||
step_engineering_string( std::string text, int digits, eng_prefixed_t, bool increment )
|
||||
{
|
||||
return step_engineering_string( text, digits, false, increment );
|
||||
}
|
||||
|
||||
/**
|
||||
* step a value by the smallest possible increment, using exponential notation.
|
||||
*/
|
||||
inline std::string
|
||||
step_engineering_string( std::string text, int digits, eng_exponential_t, bool increment )
|
||||
{
|
||||
return step_engineering_string( text, digits, true, increment );
|
||||
}
|
||||
|
||||
#endif // ENG_FORMAT_H_INCLUDED
|
||||
101
analyzer/analyzer/traceAnalyzer.pro
Normal file
101
analyzer/analyzer/traceAnalyzer.pro
Normal file
@@ -0,0 +1,101 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2013-11-26T20:21:15
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
QT += sql
|
||||
CONFIG += qwt
|
||||
CONFIG += python
|
||||
CONFIG += no_keywords
|
||||
|
||||
include(paths.pro)
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = traceAnalyzer
|
||||
TEMPLATE = app
|
||||
|
||||
SOURCES += main.cpp\
|
||||
businessObjects/transaction.cpp \
|
||||
businessObjects/timespan.cpp \
|
||||
data/tracedb.cpp \
|
||||
presentation/tracenavigator.cpp \
|
||||
presentation/util/colorgenerator.cpp \
|
||||
presentation/tracedrawing.cpp \
|
||||
presentation/traceplotitem.cpp \
|
||||
gototimedialog.cpp \
|
||||
presentation/traceplot.cpp \
|
||||
thirdParty/eng_formant.cpp \
|
||||
tracefiletab.cpp \
|
||||
presentation/pornotracescroller.cpp \
|
||||
traceanalyzer.cpp \
|
||||
presentation/transactiontreewidget.cpp \
|
||||
presentation/commenttreewidget.cpp \
|
||||
presentation/util/clkgrid.cpp \
|
||||
queryeditor.cpp \
|
||||
presentation/selectedtransactiontreewidget.cpp \
|
||||
businessObjects/phases/phasefactory.cpp \
|
||||
presentation/debugmessagetreewidget.cpp \
|
||||
presentation/tracePlotMouseLabel.cpp \
|
||||
evaluationtool.cpp \
|
||||
presentation/util/testlight.cpp \
|
||||
presentation/tracetesttreewidget.cpp \
|
||||
businessObjects/pythoncaller.cpp \
|
||||
businessObjects/tracetestresults.cpp \
|
||||
presentation/tracemetrictreewidget.cpp \
|
||||
businessObjects/phases/phase.cpp
|
||||
|
||||
HEADERS += businessObjects/transaction.h \
|
||||
businessObjects/timespan.h \
|
||||
businessObjects/generalinfo.h \
|
||||
data/tracedb.h \
|
||||
presentation/tracenavigator.h \
|
||||
presentation/util/colorgenerator.h \
|
||||
presentation/util/engineeringScaleDraw.h \
|
||||
presentation/tracedrawingproperties.h \
|
||||
presentation/tracedrawing.h \
|
||||
presentation/traceplotitem.h \
|
||||
gototimedialog.h \
|
||||
presentation/traceplot.h \
|
||||
thirdParty/eng_format.h \
|
||||
tracefiletab.h \
|
||||
presentation/pornotracescroller.h \
|
||||
traceanalyzer.h \
|
||||
presentation/transactiontreewidget.h \
|
||||
businessObjects/comment.h \
|
||||
presentation/commenttreewidget.h \
|
||||
businessObjects/tracetime.h \
|
||||
presentation/util/clkgrid.h \
|
||||
presentation/util/customlabelscaledraw.h \
|
||||
data/QueryTexts.h \
|
||||
queryeditor.h \
|
||||
presentation/selectedtransactiontreewidget.h \
|
||||
businessObjects/phases/phasefactory.h \
|
||||
presentation/debugmessagetreewidget.h \
|
||||
presentation/tracePlotMouseLabel.h \
|
||||
evaluationtool.h \
|
||||
presentation/util/testlight.h \
|
||||
presentation/tracetesttreewidget.h \
|
||||
businessObjects/pythoncaller.h \
|
||||
businessObjects/testresult.h \
|
||||
businessObjects/tracetestresults.h \
|
||||
presentation/tracemetrictreewidget.h \
|
||||
businessObjects/calculatedMetric.h \
|
||||
businessObjects/tracecalculatedmetrics.h \
|
||||
businessObjects/phases/phase.h
|
||||
|
||||
|
||||
FORMS += \
|
||||
gototimedialog.ui \
|
||||
tracefiletab.ui \
|
||||
traceanalyzer.ui \
|
||||
queryeditor.ui \
|
||||
preferences.ui \
|
||||
evaluationtool.ui
|
||||
|
||||
OTHER_FILES += \
|
||||
common/static/createTraceDB.sql
|
||||
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_CXXFLAGS += -Xlinker -export-dynamic
|
||||
109
analyzer/analyzer/traceanalyzer.cpp
Normal file
109
analyzer/analyzer/traceanalyzer.cpp
Normal file
@@ -0,0 +1,109 @@
|
||||
#include "traceanalyzer.h"
|
||||
#include "ui_traceanalyzer.h"
|
||||
#include "tracefiletab.h"
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QDateTime>
|
||||
#include "QMessageBox"
|
||||
#include <iostream>
|
||||
|
||||
void TraceAnalyzer::setUpStatusBar()
|
||||
{
|
||||
statusLabel = new QLabel(this);
|
||||
statusBar()->addWidget(statusLabel);
|
||||
}
|
||||
|
||||
void TraceAnalyzer::setUpGui()
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setUpStatusBar();
|
||||
ui->traceFileTabs->clear();
|
||||
}
|
||||
|
||||
|
||||
TraceAnalyzer::TraceAnalyzer(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::TraceAnalyzer)
|
||||
{
|
||||
setUpGui();
|
||||
}
|
||||
|
||||
|
||||
TraceAnalyzer::TraceAnalyzer(QSet<QString> paths, StartupOption option, QWidget *parent):
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::TraceAnalyzer)
|
||||
{
|
||||
setUpGui();
|
||||
|
||||
for(const QString& path : paths)
|
||||
openTracefile(path);
|
||||
|
||||
if(option == StartupOption::runTests)
|
||||
{
|
||||
ui->actionTest->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
TraceAnalyzer::~TraceAnalyzer()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_actionOpen_triggered()
|
||||
{
|
||||
QStringList paths = QFileDialog::getOpenFileNames(this,tr("Open Tracefile"),"",tr("Tracefile(*.tdb)"));
|
||||
if(paths.isEmpty())
|
||||
return;
|
||||
|
||||
for(const QString &path: paths)
|
||||
{
|
||||
openTracefile(path);
|
||||
}
|
||||
}
|
||||
|
||||
void TraceAnalyzer::openTracefile(const QString &path)
|
||||
{
|
||||
if(openedTraceFiles.contains(path))
|
||||
return;
|
||||
|
||||
TraceFileTab* tab = new TraceFileTab(this, path);
|
||||
connect(tab, SIGNAL(statusChanged(QString)), this, SLOT(statusChanged(QString)));
|
||||
ui->traceFileTabs->addTab(tab,QFileInfo(path).baseName());
|
||||
openedTraceFiles.insert(path);
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_traceFileTabs_tabCloseRequested(int index)
|
||||
{
|
||||
TraceFileTab* traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
|
||||
openedTraceFiles.remove(traceFileTab->getPathToTraceFile());
|
||||
ui->traceFileTabs->removeTab(index);
|
||||
delete traceFileTab;
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_actionClose_all_triggered()
|
||||
{
|
||||
while(ui->traceFileTabs->count())
|
||||
on_traceFileTabs_tabCloseRequested(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TraceAnalyzer::statusChanged(QString message)
|
||||
{
|
||||
statusLabel->setText(message + " - (" + QTime::currentTime().toString() + ")");
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_actionTest_triggered()
|
||||
{
|
||||
evaluationTool.raise();
|
||||
evaluationTool.activateWindow();
|
||||
evaluationTool.showAndRunTests(openedTraceFiles.toList());
|
||||
}
|
||||
|
||||
void TraceAnalyzer::on_actionMetrics_triggered()
|
||||
{
|
||||
evaluationTool.raise();
|
||||
evaluationTool.activateWindow();
|
||||
evaluationTool.showAndEvaluateMetrics(openedTraceFiles.toList());
|
||||
|
||||
}
|
||||
52
analyzer/analyzer/traceanalyzer.h
Normal file
52
analyzer/analyzer/traceanalyzer.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef TRACEANALYZER_H
|
||||
#define TRACEANALYZER_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QLabel>
|
||||
#include <vector>
|
||||
#include <QString>
|
||||
#include <QSet>
|
||||
#include "evaluationtool.h"
|
||||
|
||||
namespace Ui {
|
||||
class TraceAnalyzer;
|
||||
}
|
||||
|
||||
enum class StartupOption{showPlots,runTests};
|
||||
enum class OpenOptions{files,folders};
|
||||
|
||||
class TraceAnalyzer : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TraceAnalyzer(QWidget *parent = 0);
|
||||
explicit TraceAnalyzer(QSet<QString> paths, StartupOption option, QWidget *parent = 0);
|
||||
|
||||
~TraceAnalyzer();
|
||||
EvaluationTool evaluationTool;
|
||||
|
||||
void setUpStatusBar();
|
||||
void setUpGui();
|
||||
|
||||
private:
|
||||
void openTracefile(const QString &path);
|
||||
QLabel *statusLabel;
|
||||
QSet<QString> openedTraceFiles;
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_actionOpen_triggered();
|
||||
void on_traceFileTabs_tabCloseRequested(int index);
|
||||
void on_actionClose_all_triggered();
|
||||
void on_actionTest_triggered();
|
||||
|
||||
void on_actionMetrics_triggered();
|
||||
|
||||
public Q_SLOTS:
|
||||
void statusChanged(QString message);
|
||||
|
||||
private:
|
||||
Ui::TraceAnalyzer *ui;
|
||||
};
|
||||
|
||||
#endif // TRACEANALYZER_H
|
||||
126
analyzer/analyzer/traceanalyzer.ui
Normal file
126
analyzer/analyzer/traceanalyzer.ui
Normal file
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TraceAnalyzer</class>
|
||||
<widget class="QMainWindow" name="TraceAnalyzer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>600</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Trace Analyzer</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="traceFileTabs">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="documentMode">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="tabsClosable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Tab 1</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Tab 2</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionOpen"/>
|
||||
<addaction name="actionClose_all"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionTest"/>
|
||||
<addaction name="actionMetrics"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<addaction name="actionInfo"/>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<action name="actionOpen">
|
||||
<property name="text">
|
||||
<string>Open</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose_all">
|
||||
<property name="text">
|
||||
<string>Close all</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInfo">
|
||||
<property name="text">
|
||||
<string>Info</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="text">
|
||||
<string>About</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPreferences">
|
||||
<property name="text">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+P</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTest">
|
||||
<property name="text">
|
||||
<string>Test</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+T</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMetrics">
|
||||
<property name="text">
|
||||
<string>Metrics</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+M</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
59
analyzer/analyzer/tracefiletab.cpp
Normal file
59
analyzer/analyzer/tracefiletab.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "tracefiletab.h"
|
||||
#include "ui_tracefiletab.h"
|
||||
#include "queryeditor.h"
|
||||
#include "QFileInfo"
|
||||
#include "qmessagebox.h"
|
||||
#include <iostream>
|
||||
#include <iostream>
|
||||
|
||||
TraceFileTab::TraceFileTab(QWidget *parent,const QString& path) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::TraceFileTab)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
this->path = path;
|
||||
initNavigatorAndItsDependentWidgets(path);
|
||||
setUpFileWatcher(path);
|
||||
ui->fileDescriptionEdit->setPlainText(navigator->GeneralTraceInfo().description);
|
||||
tracefileChanged();
|
||||
}
|
||||
|
||||
TraceFileTab::~TraceFileTab()
|
||||
{
|
||||
navigator->commitChangesToDB();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path)
|
||||
{
|
||||
navigator = new TraceNavigator(path,this);
|
||||
|
||||
ui->traceplot->init(navigator);
|
||||
|
||||
ui->pornoTraceScroller->init(navigator, ui->traceplot);
|
||||
connect(this,SIGNAL(colorGroupingChanged(ColorGrouping)),ui->pornoTraceScroller,SLOT(colorGroupingChanged(ColorGrouping)));
|
||||
|
||||
ui->selectedTransactionTree->init(navigator);
|
||||
//ui->debugMessages->init(navigator,ui->traceplot);
|
||||
ui->commentTree->init(navigator);
|
||||
|
||||
}
|
||||
|
||||
void TraceFileTab::setUpFileWatcher(QString path)
|
||||
{
|
||||
fileWatcher = new QFileSystemWatcher(QStringList(path),this);
|
||||
QObject::connect(fileWatcher,SIGNAL(fileChanged(QString)),this,SLOT(tracefileChanged()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
void TraceFileTab::tracefileChanged()
|
||||
{
|
||||
Q_EMIT statusChanged(QString("Last Database Refresh"));
|
||||
navigator->refreshData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
43
analyzer/analyzer/tracefiletab.h
Normal file
43
analyzer/analyzer/tracefiletab.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef TRACEFILETAB_H
|
||||
#define TRACEFILETAB_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QString>
|
||||
#include <QFileSystemWatcher>
|
||||
#include "presentation/tracenavigator.h"
|
||||
#include "presentation/traceplot.h"
|
||||
#include "presentation/pornotracescroller.h"
|
||||
|
||||
namespace Ui {
|
||||
class TraceFileTab;
|
||||
}
|
||||
|
||||
class TraceFileTab : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TraceFileTab(QWidget *parent,const QString& path);
|
||||
~TraceFileTab();
|
||||
|
||||
void setUpFileWatcher(QString filename);
|
||||
void initNavigatorAndItsDependentWidgets(QString path);
|
||||
QString getPathToTraceFile(){return path;}
|
||||
|
||||
private:
|
||||
QString path;
|
||||
Ui::TraceFileTab *ui;
|
||||
TraceNavigator *navigator;
|
||||
QFileSystemWatcher *fileWatcher;
|
||||
void setUpQueryEditor(QString path);
|
||||
|
||||
public Q_SLOTS:
|
||||
void tracefileChanged();
|
||||
|
||||
Q_SIGNALS:
|
||||
void statusChanged(QString);
|
||||
void colorGroupingChanged(ColorGrouping colorgrouping);
|
||||
|
||||
};
|
||||
|
||||
#endif // TRACEFILETAB_H
|
||||
182
analyzer/analyzer/tracefiletab.ui
Normal file
182
analyzer/analyzer/tracefiletab.ui
Normal file
@@ -0,0 +1,182 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TraceFileTab</class>
|
||||
<widget class="QWidget" name="TraceFileTab">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1235</width>
|
||||
<height>937</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout" stretch="7,0">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
|
||||
<item>
|
||||
<widget class="TracePlot" name="traceplot">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>4</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="focusPolicy">
|
||||
<enum>Qt::StrongFocus</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="PornoTraceScroller" name="pornoTraceScroller">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>4</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
|
||||
<item>
|
||||
<widget class="SelectedTransactionTreeWidget" name="selectedTransactionTree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>3</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<attribute name="headerStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="CommentTreeWidget" name="commentTree">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string notr="true">1</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="fileDescriptionEdit">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>1</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>TracePlot</class>
|
||||
<extends>QListView</extends>
|
||||
<header>presentation/traceplot.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PornoTraceScroller</class>
|
||||
<extends>QListView</extends>
|
||||
<header>presentation/pornotracescroller.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>CommentTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/commenttreewidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SelectedTransactionTreeWidget</class>
|
||||
<extends>QTreeWidget</extends>
|
||||
<header>presentation/selectedtransactiontreewidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,4 +1,4 @@
|
||||
TEMPLATE = app
|
||||
TEMPLATE = app
|
||||
CONFIG += console
|
||||
CONFIG -= app_bundle
|
||||
CONFIG -= qt
|
||||
@@ -6,28 +6,20 @@ CONFIG -= qt
|
||||
|
||||
LIBS += -L/opt/systemc/lib-linux64 -lsystemc
|
||||
LIBS += -L/opt/boost/lib -lboost_filesystem -lboost_system
|
||||
LIBS += -lsqlite3
|
||||
LIBS += -L/opt/sqlite3/lib -lsqlite3
|
||||
LIBS += -lpthread
|
||||
LIBS += -L ../src/common/third_party/DRAMPower/src -ldrampower
|
||||
INCLUDEPATH += ../src/common/third_party/DRAMPower/src
|
||||
INCLUDEPATH += /opt/systemc/include
|
||||
INCLUDEPATH += /opt/boost/include
|
||||
INCLUDEPATH += /opt/sqlite3/include
|
||||
|
||||
DEFINES += TIXML_USE_STL
|
||||
DEFINES += SC_INCLUDE_DYNAMIC_PROCESSES
|
||||
|
||||
CONFIG(release){
|
||||
DEFINES += NDEBUG
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O1
|
||||
QMAKE_CXXFLAGS_RELEASE -= -O2
|
||||
QMAKE_CXXFLAGS_RELEASE *= -O3
|
||||
}
|
||||
|
||||
QMAKE_CXXFLAGS += -std=c++11
|
||||
QMAKE_CXXFLAGS += -isystem /opt/systemc/include
|
||||
QMAKE_CXXFLAGS += -isystem /opt/boost/include
|
||||
#QMAKE_CXXFLAGS = -Wno-unused-variable
|
||||
|
||||
SOURCES += \
|
||||
../src/common/third_party/tinyxml2.cpp \
|
||||
@@ -62,11 +54,14 @@ SOURCES += \
|
||||
../src/controller/core/ControllerState.cpp \
|
||||
../src/controller/core/ControllerCore.cpp \
|
||||
../src/controller/core/Command.cpp \
|
||||
../src/controller/core/BankStates.cpp \
|
||||
../src/simulation/SimulationManager.cpp \
|
||||
../src/simulation/Simulation.cpp \
|
||||
../src/simulation/MemoryManager.cpp \
|
||||
../src/simulation/main.cpp
|
||||
../src/simulation/main.cpp \
|
||||
../src/common/libDRAMPower.cpp \
|
||||
../src/controller/core/RowBufferStates.cpp \
|
||||
../src/controller/scheduler/Scheduler.cpp \
|
||||
../src/controller/scheduler/readwritegrouper.cpp
|
||||
|
||||
HEADERS += \
|
||||
../src/common/third_party/tinyxml2.h \
|
||||
@@ -84,7 +79,6 @@ HEADERS += \
|
||||
../src/controller/core/powerdown/PowerDownManagerTimeout.h \
|
||||
../src/controller/core/powerdown/PowerDownManagerBankwise.h \
|
||||
../src/controller/core/powerdown/PowerDownManager.h \
|
||||
../src/controller/core/powerdown/IPowerDownManager.h \
|
||||
../src/controller/scheduler/ThreadLoad.h \
|
||||
../src/controller/scheduler/Scheduler.h \
|
||||
../src/controller/scheduler/PARBS.h \
|
||||
@@ -113,7 +107,6 @@ HEADERS += \
|
||||
../src/controller/core/ControllerState.h \
|
||||
../src/controller/core/ControllerCore.h \
|
||||
../src/controller/core/Command.h \
|
||||
../src/controller/core/BankStates.h \
|
||||
../src/simulation/TracePlayer.h \
|
||||
../src/simulation/SimulationManager.h \
|
||||
../src/simulation/Simulation.h \
|
||||
@@ -121,5 +114,8 @@ HEADERS += \
|
||||
../src/simulation/ISimulation.h \
|
||||
../src/simulation/Dram.h \
|
||||
../src/simulation/Arbiter.h
|
||||
../src/common/libDRAMPower.h \
|
||||
../src/controller/core/RowBufferStates.h \
|
||||
../src/controller/scheduler/readwritegrouper.h
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
|
||||
<dramconfig>
|
||||
<!-- <dramconfig>
|
||||
<addressmap length="29">
|
||||
<channel from="27" to="28" />
|
||||
<row from="14" to="26" />
|
||||
@@ -9,3 +9,13 @@
|
||||
<bytes from="0" to="3" />
|
||||
</addressmap>
|
||||
</dramconfig>
|
||||
-->
|
||||
<dramconfig>
|
||||
<addressmap length="29">
|
||||
<channel from="27" to="28" />
|
||||
<row from="14" to="26" />
|
||||
<colum from="7" to="13" />
|
||||
<bank from="4" to="6" />
|
||||
<bytes from="0" to="3" />
|
||||
</addressmap>
|
||||
</dramconfig>
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="50" />
|
||||
<parameter id="scheduler" type="string" value="FIFO" />
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="TimeoutPDN" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="100" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
<memspec>
|
||||
<memconfig>
|
||||
<parameter id="bankwiseLogic" type="bool" value="0" />
|
||||
<parameter id="bankwiseLogic" type="bool" value="1" />
|
||||
<parameter id="openPagePolicy" type="bool" value="1" />
|
||||
<parameter id="adaptiveOpenPagePolicy" type="bool" value="0" />
|
||||
<parameter id="refreshAwareScheduling" type="bool" value="1" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="2000" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="50" />
|
||||
<parameter id="scheduler" type="string" value="FR_FCFS" />
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="TimeoutPDN" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="100" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -9,5 +9,7 @@
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="3" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -9,5 +9,7 @@
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="3" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -9,5 +9,7 @@
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="3" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
15
dram/resources/configs/memconfigs/par_bs.xml
Normal file
15
dram/resources/configs/memconfigs/par_bs.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<memspec>
|
||||
<memconfig>
|
||||
<parameter id="bankwiseLogic" type="bool" value="0" />
|
||||
<parameter id="openPagePolicy" type="bool" value="1" />
|
||||
<parameter id="adaptiveOpenPagePolicy" type="bool" value="0" />
|
||||
<parameter id="refreshAwareScheduling" type="bool" value="1" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="50" />
|
||||
<parameter id="scheduler" type="string" value="PAR_BS" />
|
||||
<parameter id="capsize" type="uint" value="8" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="3" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="0" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
@@ -6,8 +6,10 @@
|
||||
<parameter id="refreshAwareScheduling" type="bool" value="0" />
|
||||
<parameter id="maxNrOfTransactionsInDram" type="uint" value="50" />
|
||||
<parameter id="scheduler" type="string" value="PAR_BS" />
|
||||
<parameter id="capsize" type="uint" value="5" />
|
||||
<parameter id="capsize" type="uint" value="8" />
|
||||
<parameter id="powerDownMode" type="string" value="Staggered" />
|
||||
<parameter id="powerDownTimeout" type="uint" value="3" />
|
||||
|
||||
<parameter id="databaseRecordingEnabled" type="bool" value="1" />
|
||||
</memconfig>
|
||||
</memspec>
|
||||
|
||||
@@ -32,17 +32,23 @@ def getTraceLength(connection):
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
#@metric
|
||||
#def latency_histogram(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("SELECT ((p2.PhaseEnd - p1.PhaseEnd)/1000) 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\" ")
|
||||
# result = cursor.fetchall()
|
||||
# #result.sort()
|
||||
# #print(max(result)[0])
|
||||
# import matplotlib.pyplot as plt
|
||||
# plt.hist(result, bins=max(result)[0]/100, histtype='barstacked')
|
||||
# plt.savefig('hist.png')
|
||||
# return "Saved as hist.png"
|
||||
def getClock(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT clk FROM GeneralInfo")
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
@metric
|
||||
def latency_histogram(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT ((p2.PhaseEnd - p1.PhaseEnd)/1000) 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\" ")
|
||||
result = cursor.fetchall()
|
||||
#result.sort()
|
||||
#print(max(result)[0])
|
||||
import matplotlib.pyplot as plt
|
||||
plt.hist(result, bins=max(result)[0], histtype='barstacked')
|
||||
plt.savefig('hist.png')
|
||||
return "Saved as hist.png"
|
||||
|
||||
@metric
|
||||
def average_response_latency_in_ns(connection):
|
||||
@@ -53,8 +59,6 @@ def average_response_latency_in_ns(connection):
|
||||
result = cursor.fetchone()
|
||||
return round(result[0],1)
|
||||
|
||||
|
||||
|
||||
def refreshMissDecision(connection,calculatedMetrics):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("""SELECT phases.ID,PhaseBegin,PhaseEnd,TBank FROM Phases INNER JOIN transactions on transactions.id = phases.transact WHERE PhaseName='AUTO_REFRESH' """)
|
||||
@@ -88,51 +92,18 @@ def refreshMissDecision(connection,calculatedMetrics):
|
||||
totalDecisios = totalDecisios + 1
|
||||
if(earliestReq[0] != earliestResp[0]):
|
||||
missDecisions = missDecisions + 1
|
||||
print("earliest Req: {0}| earliest Res: {1}".format(earliestReq[0], earliestResp[0]))
|
||||
#print("earliest Req: {0}| earliest Res: {1}".format(earliestReq[0], earliestResp[0]))
|
||||
end
|
||||
|
||||
|
||||
|
||||
if(totalDecisios != 0):
|
||||
calculatedMetrics.append(("Total Missdecisions", missDecisions))
|
||||
#calculatedMetrics.append(("Total Missdecisions", missDecisions))
|
||||
calculatedMetrics.append(("Relative Missdecisions", 1.0*missDecisions/totalDecisios))
|
||||
else:
|
||||
calculatedMetrics.append(("Total Missdecisions", 0))
|
||||
calculatedMetrics.append(("Relative Missdecisions", 0))
|
||||
|
||||
# @metric
|
||||
# def median_response_latency_in_ns(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("""SELECT median(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
|
||||
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0],1)
|
||||
|
||||
# @metric
|
||||
# def max_response_latency_in_ns(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("""SELECT max(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
|
||||
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0],1)
|
||||
|
||||
# @metric
|
||||
# def min_response_latency_in_ns(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("""SELECT min(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
|
||||
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0],1)
|
||||
|
||||
# @metric
|
||||
# def stdDev_response_latency_in_ns(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("""SELECT stdev(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
|
||||
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' """)
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0],1)
|
||||
|
||||
|
||||
@threadMetric
|
||||
def average_response_latency_in_ns(connection, thread):
|
||||
cursor = connection.cursor()
|
||||
@@ -143,22 +114,37 @@ def average_response_latency_in_ns(connection, thread):
|
||||
result = cursor.fetchone()
|
||||
return round(result[0],1)
|
||||
|
||||
# @threadMetric
|
||||
# def median_response_latency_in_ns(connection, thread):
|
||||
# cursor = connection.cursor()
|
||||
# query = """SELECT median(PhaseBegin-timeOfGeneration)/1000 FROM transactions INNER JOIN Phases
|
||||
# ON phases.transact = transactions.ID WHERE PhaseName='RESP' AND TThread = :Thread """
|
||||
def addStallTime(times,begin,end):
|
||||
time = begin
|
||||
while time <= end:
|
||||
if(time in times):
|
||||
times[time] = times[time] + 1
|
||||
else:
|
||||
times[time] = 1
|
||||
time = time + 1
|
||||
|
||||
# cursor.execute(query, {"Thread": thread})
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0],1)
|
||||
#@threadMetric
|
||||
def paralellism(connection, thread):
|
||||
cursor = connection.cursor()
|
||||
stalltimes = {}
|
||||
query = """SELECT transactions.ID,MIN(phaseBegin)/:clk,MAX(phaseEnd)/:clk
|
||||
from phases inner join transactions on phases.transact=transactions.id
|
||||
where phaseName Not in ('REQ','RESP') and tthread=:Thread group by transactions.ID """
|
||||
|
||||
# @metric
|
||||
# def number_of_activates(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName = 'ACT'")
|
||||
# result = cursor.fetchone()
|
||||
# return result[0]
|
||||
cursor.execute(query, {"Thread": thread, "clk" : getClock(connection)})
|
||||
for currentRow in cursor:
|
||||
addStallTime(stalltimes,currentRow[1],currentRow[2])
|
||||
para = 0
|
||||
for time in stalltimes:
|
||||
para = para + stalltimes[time]
|
||||
return round(para/len(stalltimes),2)
|
||||
|
||||
@metric
|
||||
def number_of_activates(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName = 'ACT'")
|
||||
result = cursor.fetchone()
|
||||
return result[0]
|
||||
|
||||
# @metric
|
||||
# def number_of_precharges(connection):
|
||||
@@ -167,12 +153,12 @@ def average_response_latency_in_ns(connection, thread):
|
||||
# result = cursor.fetchone()
|
||||
# return result[0]
|
||||
|
||||
# @metric
|
||||
# def accesses_per_activate(connection):
|
||||
# cursor = connection.cursor()
|
||||
# cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('REQ')")
|
||||
# result = cursor.fetchone()
|
||||
# return round(result[0]*1.0/number_of_activates(connection),1)
|
||||
@metric
|
||||
def accesses_per_activate(connection):
|
||||
cursor = connection.cursor()
|
||||
cursor.execute("SELECT COUNT(*) FROM Phases WHERE PhaseName IN ('REQ')")
|
||||
result = cursor.fetchone()
|
||||
return round(result[0]*1.0/number_of_activates(connection),1)
|
||||
|
||||
def timeInPowerStates(connection):
|
||||
totalTimeAllBanks = getTraceLength(connection)*getNumberOfBanks(connection)
|
||||
@@ -259,29 +245,30 @@ def passRatio(connection):
|
||||
|
||||
def calculateMetrics(pathToTrace):
|
||||
connection = sqlite3.connect(pathToTrace)
|
||||
#connection.create_aggregate("median", 1, pystaggrelite3.median)
|
||||
#connection.create_aggregate("stdev", 1, pystaggrelite3.stdev)
|
||||
|
||||
calculatedMetrics = []
|
||||
|
||||
print("================================")
|
||||
print("Calculating metrics for {0}".format(pathToTrace))
|
||||
|
||||
|
||||
for metric in metrics:
|
||||
res = (metric.__name__.replace("_"," "), metric(connection))
|
||||
print("{0}: {1}".format(res[0],res[1]))
|
||||
calculatedMetrics.append(res)
|
||||
|
||||
for thread in getThreads(connection):
|
||||
for metric in threadMetrics:
|
||||
res = ("Thread " + str(thread) + " " + metric.__name__.replace("_"," "), metric(connection, thread))
|
||||
if(len(getThreads(connection))==1):
|
||||
for metric in metrics:
|
||||
res = (metric.__name__.replace("_"," "), metric(connection))
|
||||
print("{0}: {1}".format(res[0],res[1]))
|
||||
calculatedMetrics.append(res)
|
||||
|
||||
calculatedMetrics.append(("test",0))
|
||||
#calculatedMetrics.extend(passRatio(connection))
|
||||
if(len(getThreads(connection))>1):
|
||||
# for thread in getThreads(connection):
|
||||
# for metric in threadMetrics:
|
||||
# res = ("Thread " + str(thread) + " " + metric.__name__.replace("_"," "), metric(connection, thread))
|
||||
# print("{0}: {1}".format(res[0],res[1]))
|
||||
# calculatedMetrics.append(res)
|
||||
calculatedMetrics.extend(passRatio(connection))
|
||||
#refreshMissDecision(connection, calculatedMetrics)
|
||||
|
||||
#calculatedMetrics.extend(timeInPowerStates(connection))
|
||||
#print(calculatedMetrics[-1])
|
||||
#print(calculatedMetrics[-2])
|
||||
|
||||
#refreshMissDecision(connection, calculatedMetrics)
|
||||
print(calculatedMetrics[-1])
|
||||
|
||||
@@ -9,14 +9,15 @@
|
||||
|
||||
<memconfigs>
|
||||
<memconfig>fifo.xml</memconfig>
|
||||
</memconfigs>
|
||||
<!-- <memconfig>fr_fcfs.xml</memconfig>
|
||||
<memconfig>par_bs.xml</memconfig>
|
||||
--> </memconfigs>
|
||||
<trace-setups>
|
||||
|
||||
<trace-setup id="simple">
|
||||
<device >trace3.stl</device>
|
||||
</trace-setup>
|
||||
|
||||
|
||||
<trace-setup id="media">
|
||||
<device>mediabench-epic_32.stl</device>
|
||||
</trace-setup>
|
||||
|
||||
</trace-setups>
|
||||
</simulation>
|
||||
|
||||
@@ -11,41 +11,41 @@ using namespace std;
|
||||
void DebugManager::printDebugMessage(string sender, string message)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (whiteList.count(sender))
|
||||
{
|
||||
if (writeToConsole)
|
||||
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
|
||||
if (whiteList.count(sender))
|
||||
{
|
||||
if (writeToConsole)
|
||||
cout << " at " << sc_time_stamp() << "\t in " << sender << "\t: " << message << endl;
|
||||
|
||||
if (writeToFile && debugFile)
|
||||
debugFile << " at " << sc_time_stamp() << " in " << sender << "\t: " << message << "\n";
|
||||
}
|
||||
if (writeToFile && debugFile)
|
||||
debugFile << " at " << sc_time_stamp() << " in " << sender << "\t: " << message << "\n";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void DebugManager::openDebugFile(string filename)
|
||||
{
|
||||
if(debugFile)
|
||||
debugFile.close();
|
||||
debugFile.open(filename);
|
||||
}
|
||||
|
||||
void DebugManager::addToWhiteList(string sender)
|
||||
{
|
||||
whiteList.insert(sender);
|
||||
whiteList.insert(sender);
|
||||
}
|
||||
|
||||
void DebugManager::addToWhiteList(vector<string> senders)
|
||||
{
|
||||
for (string sender : senders)
|
||||
addToWhiteList(sender);
|
||||
for (string sender : senders)
|
||||
addToWhiteList(sender);
|
||||
}
|
||||
|
||||
DebugManager::DebugManager() :
|
||||
writeToConsole(true), writeToFile(true)
|
||||
writeToConsole(true), writeToFile(true)
|
||||
{
|
||||
}
|
||||
|
||||
void DebugManager::setDebugFile(std::string filename)
|
||||
{
|
||||
if(debugFile)
|
||||
debugFile.close();
|
||||
debugFile.open(filename);
|
||||
}
|
||||
|
||||
DebugManager::~DebugManager()
|
||||
{
|
||||
debugFile.close();
|
||||
debugFile.close();
|
||||
}
|
||||
|
||||
@@ -15,32 +15,28 @@
|
||||
class DebugManager
|
||||
{
|
||||
public:
|
||||
~DebugManager();
|
||||
static inline DebugManager& getInstance()
|
||||
{
|
||||
static DebugManager manager;
|
||||
return manager;
|
||||
}
|
||||
~DebugManager();
|
||||
static inline DebugManager& getInstance()
|
||||
{
|
||||
static DebugManager manager;
|
||||
return manager;
|
||||
}
|
||||
|
||||
bool writeToConsole;
|
||||
bool writeToFile;
|
||||
bool writeToConsole;
|
||||
bool writeToFile;
|
||||
|
||||
void printDebugMessage(std::string message, std::string sender);
|
||||
void printDebugMessage(std::string sender, std::string message);
|
||||
void openDebugFile(std::string filename);
|
||||
|
||||
void addToWhiteList(std::string sender);
|
||||
void addToWhiteList(std::vector<std::string> senders);
|
||||
|
||||
void setDebugFile(std::string filename);
|
||||
void addToWhiteList(std::string sender);
|
||||
void addToWhiteList(std::vector<std::string> senders);
|
||||
|
||||
private:
|
||||
DebugManager();
|
||||
DebugManager(const DebugManager&){}
|
||||
|
||||
ofstream debugFile;
|
||||
|
||||
DebugManager();
|
||||
DebugManager(const DebugManager&){};
|
||||
|
||||
std::set<std::string> whiteList;
|
||||
|
||||
ofstream debugFile;
|
||||
std::set<std::string> whiteList;
|
||||
};
|
||||
|
||||
#endif /* DEBUGMANAGER_H_ */
|
||||
|
||||
@@ -12,27 +12,30 @@ using namespace std;
|
||||
string TlmRecorder::dbName = "";
|
||||
string TlmRecorder::sqlScriptURI = "";
|
||||
string TlmRecorder::senderName = "TlmRecorder";
|
||||
|
||||
bool TlmRecorder::recordingEnabled = true;
|
||||
|
||||
// ------------- public -----------------------
|
||||
|
||||
TlmRecorder::TlmRecorder() :
|
||||
transactionIDCounter(1), recordingEndTime(SC_ZERO_TIME)
|
||||
totalNumTransactions(1), simulationTimeCoveredByRecording(SC_ZERO_TIME)
|
||||
{
|
||||
recordedData.reserve(transactionCommitRate);
|
||||
setUpTransactionTerminatingPhases();
|
||||
openDB(TlmRecorder::dbName.c_str());
|
||||
char * sErrMsg;
|
||||
sqlite3_exec(db, "PRAGMA main.page_size = 4096", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.cache_size=10000", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.locking_mode=EXCLUSIVE", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.synchronous=OFF", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA journal_mode = OFF", NULL, NULL, &sErrMsg);
|
||||
if(recordingEnabled)
|
||||
{
|
||||
recordedData.reserve(transactionCommitRate);
|
||||
setUpTransactionTerminatingPhases();
|
||||
openDB(TlmRecorder::dbName.c_str());
|
||||
char * sErrMsg;
|
||||
sqlite3_exec(db, "PRAGMA main.page_size = 4096", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.cache_size=10000", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.locking_mode=EXCLUSIVE", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA main.synchronous=OFF", NULL, NULL, &sErrMsg);
|
||||
sqlite3_exec(db, "PRAGMA journal_mode = OFF", NULL, NULL, &sErrMsg);
|
||||
|
||||
createTables(TlmRecorder::sqlScriptURI);
|
||||
prepareSqlStatements();
|
||||
createTables(TlmRecorder::sqlScriptURI);
|
||||
prepareSqlStatements();
|
||||
|
||||
printDebugMessage("Starting new database transaction");
|
||||
printDebugMessage("Starting new database transaction");
|
||||
}
|
||||
}
|
||||
|
||||
TlmRecorder::~TlmRecorder()
|
||||
@@ -41,76 +44,63 @@ TlmRecorder::~TlmRecorder()
|
||||
closeConnection();
|
||||
}
|
||||
|
||||
void TlmRecorder::recordDummy(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
// static unsigned int id = 0;
|
||||
// RecordingData data(id);
|
||||
|
||||
// insertTransactionInDB(data,trans);
|
||||
// insertRangeInDB(id,SC_ZERO_TIME,SC_ZERO_TIME);
|
||||
// for(int i=0;i<5;i++)
|
||||
// {
|
||||
// string phaseName("Phase " + to_string(id));
|
||||
// sqlite3_bind_text(insertPhaseStatement, 1, phaseName.c_str(), phaseName.length(), 0);
|
||||
// sqlite3_bind_int64(insertPhaseStatement, 2, 0);
|
||||
// sqlite3_bind_int64(insertPhaseStatement, 3, 2);
|
||||
// sqlite3_bind_int(insertPhaseStatement, 4, id);
|
||||
// executeSqlStatement(insertPhaseStatement);
|
||||
// }
|
||||
|
||||
// id++;
|
||||
}
|
||||
|
||||
void TlmRecorder::recordPhase(tlm::tlm_generic_payload& trans, tlm::tlm_phase phase, sc_time time)
|
||||
{
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
introduceNewTransactionToSystem(trans);
|
||||
|
||||
string phaseName = phaseNameToString(phase);
|
||||
string phaseBeginPrefix = "BEGIN_";
|
||||
string phaseEndPrefix = "END_";
|
||||
|
||||
if (phaseName.find(phaseBeginPrefix) != string::npos)
|
||||
if(TlmRecorder::recordingEnabled)
|
||||
{
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName,time);
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName,time);
|
||||
}
|
||||
if (currentTransactionsInSystem.count(&trans) == 0)
|
||||
introduceTransactionSystem(trans);
|
||||
|
||||
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromDBAndInsertInDB(trans);
|
||||
string phaseName = phaseNameToString(phase);
|
||||
string phaseBeginPrefix = "BEGIN_";
|
||||
string phaseEndPrefix = "END_";
|
||||
|
||||
recordingEndTime = time;
|
||||
if (phaseName.find(phaseBeginPrefix) != string::npos)
|
||||
{
|
||||
phaseName.erase(0, phaseBeginPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].insertPhase(phaseName,time);
|
||||
}
|
||||
else
|
||||
{
|
||||
phaseName.erase(0, phaseEndPrefix.length());
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].setPhaseEnd(phaseName,time);
|
||||
}
|
||||
|
||||
bool phaseTerminatesTransaction = count(transactionTerminatingPhases.begin(),
|
||||
transactionTerminatingPhases.end(), phase) == 1;
|
||||
if (phaseTerminatesTransaction)
|
||||
removeTransactionFromSystem(trans);
|
||||
|
||||
simulationTimeCoveredByRecording = time;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::updateDataStrobe(const sc_time& begin,const sc_time& end, tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
|
||||
if(TlmRecorder::recordingEnabled)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.start = begin;
|
||||
currentTransactionsInSystem[&trans].timeOnDataStrobe.end = end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::recordDebugMessage(std::string message, sc_time time)
|
||||
{
|
||||
insertDebugMessageInDB(message, time);
|
||||
if(TlmRecorder::recordingEnabled)
|
||||
insertDebugMessageInDB(message, time);
|
||||
}
|
||||
|
||||
|
||||
// ------------- internal -----------------------
|
||||
|
||||
void TlmRecorder::introduceNewTransactionToSystem(tlm::tlm_generic_payload& trans)
|
||||
void TlmRecorder::introduceTransactionSystem(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
unsigned int id = transactionIDCounter++;
|
||||
unsigned int id = totalNumTransactions++;
|
||||
currentTransactionsInSystem[&trans].id = id;
|
||||
currentTransactionsInSystem[&trans].address = trans.get_address();
|
||||
currentTransactionsInSystem[&trans].burstlength = trans.get_streaming_width();
|
||||
@@ -130,11 +120,11 @@ void TlmRecorder::introduceNewTransactionToSystem(tlm::tlm_generic_payload& tran
|
||||
}
|
||||
}
|
||||
|
||||
void TlmRecorder::removeTransactionFromDBAndInsertInDB(tlm::tlm_generic_payload& trans)
|
||||
void TlmRecorder::removeTransactionFromSystem(tlm::tlm_generic_payload& trans)
|
||||
{
|
||||
assert(currentTransactionsInSystem.count(&trans) != 0);
|
||||
|
||||
RecordingData& recordingData = currentTransactionsInSystem[&trans];
|
||||
Transaction& recordingData = currentTransactionsInSystem[&trans];
|
||||
recordedData.push_back(recordingData);
|
||||
currentTransactionsInSystem.erase(&trans);
|
||||
}
|
||||
@@ -142,11 +132,11 @@ void TlmRecorder::removeTransactionFromDBAndInsertInDB(tlm::tlm_generic_payload&
|
||||
void TlmRecorder::commitRecordedDataToDB()
|
||||
{
|
||||
sqlite3_exec(db, "BEGIN;", 0, 0, 0);
|
||||
for(RecordingData& recordingData: recordedData)
|
||||
for(Transaction& recordingData: recordedData)
|
||||
{
|
||||
assert(recordingData.recordedPhases.size() > 0);
|
||||
insertTransactionInDB(recordingData);
|
||||
for(RecordingData::PhaseData& phaseData: recordingData.recordedPhases)
|
||||
for(Transaction::Phase& phaseData: recordingData.recordedPhases)
|
||||
{
|
||||
insertPhaseInDB(phaseData.name,phaseData.interval.start,phaseData.interval.end,recordingData.id);
|
||||
}
|
||||
@@ -161,14 +151,14 @@ void TlmRecorder::commitRecordedDataToDB()
|
||||
}
|
||||
|
||||
|
||||
void TlmRecorder::RecordingData::insertPhase(string name, sc_time begin)
|
||||
void TlmRecorder::Transaction::insertPhase(string name, sc_time begin)
|
||||
{
|
||||
recordedPhases.push_back(PhaseData(name,begin));
|
||||
recordedPhases.push_back(Phase(name,begin));
|
||||
}
|
||||
|
||||
void TlmRecorder::RecordingData::setPhaseEnd(string name, sc_time end)
|
||||
void TlmRecorder::Transaction::setPhaseEnd(string name, sc_time end)
|
||||
{
|
||||
for(PhaseData& data: recordedPhases)
|
||||
for(Phase& data: recordedPhases)
|
||||
{
|
||||
if(data.name == name)
|
||||
{
|
||||
@@ -243,8 +233,8 @@ void TlmRecorder::insertDebugMessageInDB(string message, const sc_time& time)
|
||||
|
||||
void TlmRecorder::insertGeneralInfo()
|
||||
{
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 1, transactionIDCounter - 1);
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 2, recordingEndTime.value());
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 1, totalNumTransactions - 1);
|
||||
sqlite3_bind_int64(insertGeneralInfoStatement, 2, simulationTimeCoveredByRecording.value());
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 3,
|
||||
core::Configuration::getInstance().NumberOfBanks);
|
||||
sqlite3_bind_int(insertGeneralInfoStatement, 4, core::Configuration::getInstance().Timings.clk.value());
|
||||
@@ -255,7 +245,7 @@ void TlmRecorder::insertGeneralInfo()
|
||||
executeSqlStatement(insertGeneralInfoStatement);
|
||||
}
|
||||
|
||||
void TlmRecorder::insertTransactionInDB(RecordingData& recordingData)
|
||||
void TlmRecorder::insertTransactionInDB(Transaction& recordingData)
|
||||
{
|
||||
sqlite3_bind_int(insertTransactionStatement, 1, recordingData.id);
|
||||
sqlite3_bind_int(insertTransactionStatement, 2, recordingData.id);
|
||||
@@ -324,12 +314,15 @@ void TlmRecorder::printDebugMessage(std::string message)
|
||||
|
||||
void TlmRecorder::closeConnection()
|
||||
{
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(transactionIDCounter - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
if(TlmRecorder::recordingEnabled)
|
||||
{
|
||||
commitRecordedDataToDB();
|
||||
insertGeneralInfo();
|
||||
printDebugMessage(
|
||||
"Number of transactions written to DB: " + std::to_string(totalNumTransactions - 1));
|
||||
printDebugMessage("tlmPhaseRecorder:\tEnd Recording");
|
||||
sqlite3_close(db);
|
||||
db = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ public:
|
||||
static std::string sqlScriptURI;
|
||||
static std::string dbName;
|
||||
static std::string senderName;
|
||||
static bool recordingEnabled;
|
||||
|
||||
static inline TlmRecorder& getInstance()
|
||||
{
|
||||
@@ -31,21 +32,21 @@ public:
|
||||
return decoder;
|
||||
}
|
||||
|
||||
void recordDummy(tlm::tlm_generic_payload& trans);
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
void recordMemconfig(string memconfig){this->memconfig = memconfig;}
|
||||
void recordMemspec(string memspec){this->memspec = memspec;}
|
||||
void recordTracenames(string traces){this->traces = traces;}
|
||||
|
||||
void recordPhase(tlm::tlm_generic_payload &trans, tlm::tlm_phase phase, sc_time time);
|
||||
void recordDebugMessage(std::string message, sc_time time);
|
||||
void updateDataStrobe(const sc_time& begin, const sc_time& end, tlm::tlm_generic_payload& trans);
|
||||
void closeConnection();
|
||||
|
||||
private:
|
||||
|
||||
struct RecordingData
|
||||
struct Transaction
|
||||
{
|
||||
RecordingData(){}
|
||||
RecordingData(unsigned int id):id(id){}
|
||||
Transaction(){}
|
||||
Transaction(unsigned int id):id(id){}
|
||||
|
||||
unsigned int id;
|
||||
unsigned int address;
|
||||
@@ -54,17 +55,16 @@ private:
|
||||
sc_time timeOfGeneration;
|
||||
TimeInterval timeOnDataStrobe;
|
||||
|
||||
struct PhaseData
|
||||
struct Phase
|
||||
{
|
||||
PhaseData(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
|
||||
Phase(string name,sc_time begin): name(name), interval(begin,SC_ZERO_TIME){}
|
||||
string name;
|
||||
TimeInterval interval;
|
||||
};
|
||||
std::vector<PhaseData> recordedPhases;
|
||||
std::vector<Phase> recordedPhases;
|
||||
|
||||
void insertPhase(string name,sc_time begin);
|
||||
void setPhaseEnd(string name,sc_time end);
|
||||
|
||||
};
|
||||
|
||||
std::string memconfig,memspec,traces;
|
||||
@@ -80,12 +80,12 @@ private:
|
||||
void createTables(std::string pathToURI);
|
||||
void setUpTransactionTerminatingPhases();
|
||||
|
||||
void introduceNewTransactionToSystem(tlm::tlm_generic_payload& trans);
|
||||
void removeTransactionFromDBAndInsertInDB(tlm::tlm_generic_payload& trans);
|
||||
void introduceTransactionSystem(tlm::tlm_generic_payload& trans);
|
||||
void removeTransactionFromSystem(tlm::tlm_generic_payload& trans);
|
||||
|
||||
void commitRecordedDataToDB();
|
||||
void insertGeneralInfo();
|
||||
void insertTransactionInDB(RecordingData& recordingData);
|
||||
void insertTransactionInDB(Transaction& recordingData);
|
||||
void insertRangeInDB(unsigned int id, const sc_time& begin, const sc_time& end);
|
||||
void insertPhaseInDB(string phaseName, const sc_time& begin, const sc_time& end, unsigned int transactionID);
|
||||
void insertDebugMessageInDB(string message, const sc_time& time);
|
||||
@@ -93,11 +93,11 @@ private:
|
||||
void printDebugMessage(std::string message);
|
||||
|
||||
static const int transactionCommitRate = 1000;
|
||||
vector<RecordingData> recordedData;
|
||||
map<tlm::tlm_generic_payload*, RecordingData> currentTransactionsInSystem;
|
||||
vector<Transaction> recordedData;
|
||||
map<tlm::tlm_generic_payload*, Transaction> currentTransactionsInSystem;
|
||||
|
||||
unsigned int transactionIDCounter;
|
||||
sc_time recordingEndTime;
|
||||
unsigned int totalNumTransactions;
|
||||
sc_time simulationTimeCoveredByRecording;
|
||||
|
||||
std::vector<tlm::tlm_phase> transactionTerminatingPhases;
|
||||
sqlite3 *db;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "third_party/tinyxml2.h"
|
||||
#include <iomanip>
|
||||
|
||||
//TODO : move to timing specific header
|
||||
sc_time getDistance(sc_time a, sc_time b);
|
||||
|
||||
struct TimeInterval
|
||||
@@ -30,7 +31,6 @@ struct TimeInterval
|
||||
bool intersects(TimeInterval other);
|
||||
};
|
||||
|
||||
|
||||
template<typename Key, typename Val>
|
||||
inline Val getElementFromMap(const std::map<Key, Val>& m, Key key)
|
||||
{
|
||||
@@ -70,11 +70,15 @@ static inline void loadbar(unsigned int x, unsigned int n, unsigned int w = 50,
|
||||
std::cout << "]\r" << std::flush;
|
||||
}
|
||||
|
||||
//TODO : Move to debug manager
|
||||
void reportFatal(std::string sender, std::string message);
|
||||
std::string phaseNameToString(tlm::tlm_phase phase);
|
||||
|
||||
|
||||
//TODO : Move to other source specific to xml
|
||||
std::string getFileName(std::string uri);
|
||||
bool parameterExists(tinyxml2::XMLElement* node, std::string name);
|
||||
std::string loadTextFileContents(std::string filename);
|
||||
|
||||
void loadXML(std::string uri, tinyxml2::XMLDocument& doc);
|
||||
unsigned int queryUIntParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
std::string queryStringParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
@@ -83,6 +87,5 @@ double queryDoubleParameter(tinyxml2::XMLElement* node, std::string name);
|
||||
|
||||
void setUpDummy(tlm::tlm_generic_payload& payload, Bank& bank);
|
||||
|
||||
std::string getFileName(std::string uri);
|
||||
|
||||
#endif /* UTILS_COMMON_H_ */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user