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:
Matthias Jung
2014-07-15 11:56:09 +02:00
143 changed files with 7410 additions and 1520 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,7 @@
/debug
/release
/dram/debug
/dram/release
*.tdb
*.tdb-journal
*.out

1
analyzer/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
build*

2
analyzer/analyzer/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
traceAnalyzer.pro.user
traceAnalyzer.pro.user.*

View File

@@ -0,0 +1,2 @@
dram.vp.scheduler
=================

View 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

View 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

View 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

View 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;
}

View 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

View 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");
}

View 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

View 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;
}

View 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

View 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

View 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;
}

View 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

View 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

View File

@@ -0,0 +1,12 @@
#include "tracetestresults.h"
bool TraceTestResults::hasPassedAllTests() const
{
for(const TestResult& testResult: testResults)
{
if(!testResult.hasPassed())
return false;
}
return true;
}

View 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

View 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

View 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;
}

View 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

View 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

View 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();
}
}
}

View 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

View 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();
}
}
}

View 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

View 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>

View 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");
}
}

View 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

View 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>

View 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();
}
}

View 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;
}

View 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

View 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);
}

View 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

View 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
}

View 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>

View 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());
}

View 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

View 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));
}
}

View 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

View 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;
}

View 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

View File

@@ -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()));
}

View File

@@ -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

View 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);
}
}

View 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

View 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);
}

View 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

View 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

View 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())});
}
}

View 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

View 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);
}

View 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

View 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);
}

View 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

View 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;
}

View 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

View 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();
}

View 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

View 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 &timespan)
{
parent->setText(1, prettyFormatTime(timespan.Begin()));
parent->setText(2, prettyFormatTime(timespan.End()));
}

View 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 &timespan);
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 &timespan);
void AppendPhase(QTreeWidgetItem *parent, const Phase &phase);
};
};
#endif // TRANSACTIONTREEWIDGET_H

View 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 );
}

View 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

View 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;
}

View 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

View 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

View 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

View 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());
}

View 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

View 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());
}
}

View 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

View 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>

View 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

View 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

View 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

View 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

View 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());
}

View 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

View 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>

View 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();
}

View 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

View 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>

View File

@@ -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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View 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>

View File

@@ -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>

View File

@@ -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])

View File

@@ -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>

View File

@@ -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();
}

View File

@@ -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_ */

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -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