diff --git a/analyzer/.gitignore b/analyzer/.gitignore new file mode 100644 index 00000000..30d388a1 --- /dev/null +++ b/analyzer/.gitignore @@ -0,0 +1 @@ +build* \ No newline at end of file diff --git a/analyzer/analyzer/.gitignore b/analyzer/analyzer/.gitignore new file mode 100644 index 00000000..8705455d --- /dev/null +++ b/analyzer/analyzer/.gitignore @@ -0,0 +1,2 @@ +traceAnalyzer.pro.user +traceAnalyzer.pro.user.* diff --git a/analyzer/analyzer/README.md b/analyzer/analyzer/README.md new file mode 100644 index 00000000..b202c4b5 --- /dev/null +++ b/analyzer/analyzer/README.md @@ -0,0 +1,2 @@ +dram.vp.scheduler +================= diff --git a/analyzer/analyzer/businessObjects/calculatedMetric.h b/analyzer/analyzer/businessObjects/calculatedMetric.h new file mode 100644 index 00000000..05a127f3 --- /dev/null +++ b/analyzer/analyzer/businessObjects/calculatedMetric.h @@ -0,0 +1,19 @@ +#ifndef METRIC_H +#define METRIC_H +#include + +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 diff --git a/analyzer/analyzer/businessObjects/comment.h b/analyzer/analyzer/businessObjects/comment.h new file mode 100644 index 00000000..4f9da45a --- /dev/null +++ b/analyzer/analyzer/businessObjects/comment.h @@ -0,0 +1,16 @@ +#ifndef COMMENT_H +#define COMMENT_H +#include +#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 diff --git a/analyzer/analyzer/businessObjects/generalinfo.h b/analyzer/analyzer/businessObjects/generalinfo.h new file mode 100644 index 00000000..2cdb4e8a --- /dev/null +++ b/analyzer/analyzer/businessObjects/generalinfo.h @@ -0,0 +1,25 @@ +#ifndef GENERALINFO_H +#define GENERALINFO_H +#include "timespan.h" +#include + +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 diff --git a/analyzer/analyzer/businessObjects/phases/phase.cpp b/analyzer/analyzer/businessObjects/phases/phase.cpp new file mode 100644 index 00000000..a3e467f4 --- /dev/null +++ b/analyzer/analyzer/businessObjects/phases/phase.cpp @@ -0,0 +1,111 @@ +#include "phase.h" +#include "presentation/tracedrawing.h" +#include "businessObjects/transaction.h" +#include + +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(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; +} diff --git a/analyzer/analyzer/businessObjects/phases/phase.h b/analyzer/analyzer/businessObjects/phases/phase.h new file mode 100644 index 00000000..5d827512 --- /dev/null +++ b/analyzer/analyzer/businessObjects/phases/phase.h @@ -0,0 +1,186 @@ +#ifndef BANKPHASE_H +#define BANKPHASE_H +#include "presentation/util/colorgenerator.h" +#include "presentation/tracedrawingproperties.h" +#include "businessObjects/timespan.h" +#include +#include +#include +#include +#include + +typedef unsigned int ID; +enum TextPositioning; +class Transaction; + +class Phase +{ +public: + Phase(ID id,Timespan span,const std::shared_ptr& transaction, std::vector spansOnCommandBus, std::shared_ptr 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; + std::vector spansOnCommandBus; + std::shared_ptr 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 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 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 diff --git a/analyzer/analyzer/businessObjects/phases/phasefactory.cpp b/analyzer/analyzer/businessObjects/phases/phasefactory.cpp new file mode 100644 index 00000000..37da7a93 --- /dev/null +++ b/analyzer/analyzer/businessObjects/phases/phasefactory.cpp @@ -0,0 +1,45 @@ +#include "phasefactory.h" +#include +#include "phase.h" +#include "businessObjects/transaction.h" +#include "data/tracedb.h" +#include "businessObjects/timespan.h" + +using namespace std; + +shared_ptr PhaseFactory::CreatePhase(ID id, const QString& dbPhaseName,const Timespan& span, const shared_ptr& trans, TraceDB& database) +{ + traceTime clk = database.getGeneralInfo().clkPeriod; + + if(dbPhaseName == "REQ") + return shared_ptr(new REQ(id, span,trans,{},std::shared_ptr())); + else if(dbPhaseName == "RESP") + return shared_ptr(new RESP(id, span,trans,{},std::shared_ptr())); + + else if(dbPhaseName == "PRE") + return shared_ptr(new PRE(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr())); + else if(dbPhaseName == "ACT") + return shared_ptr(new ACT(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr())); + else if(dbPhaseName == "PRE_ALL") + return shared_ptr(new PRECHARGE_ALL(id,span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr())); + else if(dbPhaseName == "AUTO_REFRESH") + return shared_ptr(new AUTO_REFRESH(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr())); + + else if(dbPhaseName == "RD") + return shared_ptr(new RD(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + else if(dbPhaseName == "RDA") + return shared_ptr(new RDA(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + else if(dbPhaseName == "WR") + return shared_ptr(new WR(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + else if(dbPhaseName == "WRA") + return shared_ptr(new WRA(id, span,trans,{Timespan(span.Begin(),span.Begin()+clk)},std::shared_ptr(new Timespan(trans->SpanOnDataStrobe())))); + + else if(dbPhaseName == "SREF") + return shared_ptr(new SREF(id, span, trans,{Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr())); + else if(dbPhaseName == "PDNA") + return shared_ptr(new PDNA(id, span,trans, {Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr())); + else if(dbPhaseName == "PDNP") + return shared_ptr(new PDNP(id, span,trans, {Timespan(span.Begin(),span.Begin()+clk),Timespan(span.End()-clk,span.End())},std::shared_ptr())); + else + throw std::runtime_error("DB phasename " + dbPhaseName.toStdString() + " unkown to phasefactory"); +} diff --git a/analyzer/analyzer/businessObjects/phases/phasefactory.h b/analyzer/analyzer/businessObjects/phases/phasefactory.h new file mode 100644 index 00000000..7ad09aba --- /dev/null +++ b/analyzer/analyzer/businessObjects/phases/phasefactory.h @@ -0,0 +1,18 @@ +#ifndef PHASEFACTORY_H +#define PHASEFACTORY_H +#include "phase.h" +#include +#include +#include "businessObjects/transaction.h" + +class TraceDB; + +class PhaseFactory +{ +private: + PhaseFactory(); +public: + static std::shared_ptr CreatePhase(ID id, const QString& dbPhaseName,const Timespan& span,const std::shared_ptr& trans, TraceDB& database); +}; + +#endif // PHASEFACTORY_H diff --git a/analyzer/analyzer/businessObjects/pythoncaller.cpp b/analyzer/analyzer/businessObjects/pythoncaller.cpp new file mode 100644 index 00000000..014bd2e9 --- /dev/null +++ b/analyzer/analyzer/businessObjects/pythoncaller.cpp @@ -0,0 +1,108 @@ +#include "pythoncaller.h" +#include +#include +#include +#include +#include + +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; +} diff --git a/analyzer/analyzer/businessObjects/pythoncaller.h b/analyzer/analyzer/businessObjects/pythoncaller.h new file mode 100644 index 00000000..370f9756 --- /dev/null +++ b/analyzer/analyzer/businessObjects/pythoncaller.h @@ -0,0 +1,26 @@ +#ifndef PYTHONCALLER_H +#define PYTHONCALLER_H +#include +#include +#include +#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 + + diff --git a/analyzer/analyzer/businessObjects/testresult.h b/analyzer/analyzer/businessObjects/testresult.h new file mode 100644 index 00000000..aca90583 --- /dev/null +++ b/analyzer/analyzer/businessObjects/testresult.h @@ -0,0 +1,22 @@ +#ifndef TESTRESULT_H +#define TESTRESULT_H +#include + +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 diff --git a/analyzer/analyzer/businessObjects/timespan.cpp b/analyzer/analyzer/businessObjects/timespan.cpp new file mode 100644 index 00000000..6249555c --- /dev/null +++ b/analyzer/analyzer/businessObjects/timespan.cpp @@ -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; +} diff --git a/analyzer/analyzer/businessObjects/timespan.h b/analyzer/analyzer/businessObjects/timespan.h new file mode 100644 index 00000000..348a7649 --- /dev/null +++ b/analyzer/analyzer/businessObjects/timespan.h @@ -0,0 +1,24 @@ +#ifndef TIMESPAN_H +#define TIMESPAN_H +#include +#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 diff --git a/analyzer/analyzer/businessObjects/tracecalculatedmetrics.h b/analyzer/analyzer/businessObjects/tracecalculatedmetrics.h new file mode 100644 index 00000000..d50bed1c --- /dev/null +++ b/analyzer/analyzer/businessObjects/tracecalculatedmetrics.h @@ -0,0 +1,46 @@ +#ifndef TRACEMETRICRESULTS_H +#define TRACEMETRICRESULTS_H +#include +#include +#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& 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 calculatedMetrics; +}; + + +#endif // TRACEMETRICRESULTS_H diff --git a/analyzer/analyzer/businessObjects/tracetestresults.cpp b/analyzer/analyzer/businessObjects/tracetestresults.cpp new file mode 100644 index 00000000..d4b59a36 --- /dev/null +++ b/analyzer/analyzer/businessObjects/tracetestresults.cpp @@ -0,0 +1,12 @@ +#include "tracetestresults.h" + + +bool TraceTestResults::hasPassedAllTests() const +{ + for(const TestResult& testResult: testResults) + { + if(!testResult.hasPassed()) + return false; + } + return true; +} diff --git a/analyzer/analyzer/businessObjects/tracetestresults.h b/analyzer/analyzer/businessObjects/tracetestresults.h new file mode 100644 index 00000000..72bc98a9 --- /dev/null +++ b/analyzer/analyzer/businessObjects/tracetestresults.h @@ -0,0 +1,22 @@ +#ifndef TRACETESTRESULT_H +#define TRACETESTRESULT_H +#include +#include +#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& getTestResults() const{return testResults;} +private: + QString traceName; + std::vector testResults; +}; + +#endif // TRACETESTRESULT_H diff --git a/analyzer/analyzer/businessObjects/tracetime.h b/analyzer/analyzer/businessObjects/tracetime.h new file mode 100644 index 00000000..88bc022c --- /dev/null +++ b/analyzer/analyzer/businessObjects/tracetime.h @@ -0,0 +1,20 @@ +#ifndef TRACETIME_H +#define TRACETIME_H +#include +#include "thirdParty/eng_format.h" + +//time in nanoseconds +typedef long long traceTime; + +inline QString formatTraceTimePretty(traceTime time) +{ + return QString::number(time/1000) + QString(" ns"); +} + +inline traceTime alignToClk(traceTime time, unsigned int clkPeriod) +{ + return round(1.0*time/clkPeriod)*clkPeriod; +} + + +#endif // TRACETIME_H diff --git a/analyzer/analyzer/businessObjects/transaction.cpp b/analyzer/analyzer/businessObjects/transaction.cpp new file mode 100644 index 00000000..2d50a287 --- /dev/null +++ b/analyzer/analyzer/businessObjects/transaction.cpp @@ -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) +{ + 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: 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: phases) + { + if(phase->isSelected(time,yVal,drawingproperties)) + return true; + } + } + + return false; +} diff --git a/analyzer/analyzer/businessObjects/transaction.h b/analyzer/analyzer/businessObjects/transaction.h new file mode 100644 index 00000000..77e49c91 --- /dev/null +++ b/analyzer/analyzer/businessObjects/transaction.h @@ -0,0 +1,45 @@ +#ifndef TRANSACTION_H +#define TRANSACTION_H +#include +#include +#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> 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); + + 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>& Phases() const{return phases;} + +}; + +#endif // TRANSACTION_H diff --git a/analyzer/analyzer/data/QueryTexts.h b/analyzer/analyzer/data/QueryTexts.h new file mode 100644 index 00000000..a8256518 --- /dev/null +++ b/analyzer/analyzer/data/QueryTexts.h @@ -0,0 +1,22 @@ +#ifndef QUERYTEXTS_H +#define QUERYTEXTS_H +#include + +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 diff --git a/analyzer/analyzer/data/tracedb.cpp b/analyzer/analyzer/data/tracedb.cpp new file mode 100644 index 00000000..1ca511ce --- /dev/null +++ b/analyzer/analyzer/data/tracedb.cpp @@ -0,0 +1,349 @@ +#include +#include +#include +#include +#include +#include +#include +#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 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> TraceDB::getTransactionsWithCustomQuery(QString queryText) +{ + QSqlQuery query(database); + query.prepare(queryText); + executeQuery(query); + return parseTransactionsFromQuery(query); +} + +vector> 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 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 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 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 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: " + formatTraceTimePretty(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 TraceDB::getComments() +{ + QSqlQuery query(database); + query.prepare("SELECT Time,Text From Comments"); + executeQuery(query); + return parseCommentsFromQuery(query); +} + + +vector TraceDB::getDebugMessagesInTimespan(const Timespan &span) +{ + selectDebugMessagesByTimespan.bindValue(":begin",span.Begin()); + selectDebugMessagesByTimespan.bindValue(":end",span.End()); + executeQuery(selectDebugMessagesByTimespan); + + return parseCommentsFromQuery(selectDebugMessagesByTimespan); +} + +vector 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 TraceDB::parseTransactionFromQuery(QSqlQuery &query) +{ + auto result = parseTransactionsFromQuery(query); + if(!result.empty()) + return result[0]; + else + return shared_ptr(); +} + +vector> TraceDB::parseTransactionsFromQuery(QSqlQuery &query) +{ + vector> 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(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 TraceDB::parseCommentsFromQuery(QSqlQuery &query) +{ + vector 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 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(); + } + } +} + diff --git a/analyzer/analyzer/data/tracedb.h b/analyzer/analyzer/data/tracedb.h new file mode 100644 index 00000000..0eea8953 --- /dev/null +++ b/analyzer/analyzer/data/tracedb.h @@ -0,0 +1,96 @@ +#ifndef TRACEDB_H +#define TRACEDB_H + +#include +#include +#include +#include +#include +#include +#include +#include +#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 comments); + void updateFileDescription(const QString &description); + void refreshData(); + + const GeneralInfo& getGeneralInfo() {return generalInfo;} + + std::vector> getTransactionsWithCustomQuery(QString queryText); + std::vector> getTransactionsInTimespan(const Timespan &span); + std::shared_ptr getNextPrecharge(ID currentTransactionId); + std::shared_ptr getNextActivate(ID currentTransactionId); + std::shared_ptr getNextRefresh(ID currentTransactionId); + + + std::shared_ptr getTransactionByID(ID id); + ID getTransactionIDFromPhaseID(ID phaseID); + + std::vector getComments(); + std::vector getDebugMessagesInTimespan(const Timespan &span); + std::vector 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 parseTransactionFromQuery(QSqlQuery &query); + std::vector> parseTransactionsFromQuery(QSqlQuery &query); + std::vector 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 + + + diff --git a/analyzer/analyzer/evaluationtool.cpp b/analyzer/analyzer/evaluationtool.cpp new file mode 100644 index 00000000..4ca3d52c --- /dev/null +++ b/analyzer/analyzer/evaluationtool.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "evaluationtool.h" +#include "ui_evaluationtool.h" + +using namespace std; + + +EvaluationTool::EvaluationTool(QWidget *parent) : + QWidget(parent), + ui(new Ui::EvaluationTool), path("../../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 paths) +{ + cleanUpUI(); + fillFileList(paths); + show(); + ui->toolBox->setCurrentIndex(0); +} + +void EvaluationTool::showAndRunTests(QList paths) +{ + cleanUpUI(); + fillFileList(paths); + show(); + ui->toolBox->setCurrentIndex(0); + runTests(); +} + +void EvaluationTool::showAndEvaluateMetrics(QList paths) +{ + cleanUpUI(); + fillFileList(paths); + show(); + ui->toolBox->setCurrentIndex(1); + calculateMetrics(); + std::cout<<"done"<clear(); + calculatedMetrics.clear(); + ui->traceMetricTreeWidget->clear(); + ui->traceTestTreeWidget->clear(); + ui->testMessage->setPlainText(QString("")); + ui->testLight->setGray(); +} + +void EvaluationTool::fillFileList(QList 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() +{ + PythonCaller pythonCaller(this->path); + 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(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() +{ + qDebug() << this->path; + PythonCaller pythonCaller(this->path); + ui->traceMetricTreeWidget->clear(); + for(int row = 0; row < traceFilesModel->rowCount(); ++row) + { + TraceFileItem* item = static_cast(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(); + } + } + +} diff --git a/analyzer/analyzer/evaluationtool.h b/analyzer/analyzer/evaluationtool.h new file mode 100644 index 00000000..c9a4bfd5 --- /dev/null +++ b/analyzer/analyzer/evaluationtool.h @@ -0,0 +1,62 @@ +#ifndef EVALUATIONTOOL_H +#define EVALUATIONTOOL_H + +#include +#include +#include +#include +#include +#include +#include +#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 paths); + void showAndRunTests(QList paths); + void showAndEvaluateMetrics(QList 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 paths); + void runTests(); + void calculateMetrics(); + void cleanUpUI(); + + + Ui::EvaluationTool *ui; + QStandardItemModel *traceFilesModel; + std::vector calculatedMetrics; + QString path; + + class TraceFileItem : public QStandardItem + { + public: + TraceFileItem(const QString& path); + QString getPath(){return path;} + + private: + QString path; + }; + +}; + +#endif // EVALUATIONTOOL_H diff --git a/analyzer/analyzer/evaluationtool.ui b/analyzer/analyzer/evaluationtool.ui new file mode 100644 index 00000000..0b773843 --- /dev/null +++ b/analyzer/analyzer/evaluationtool.ui @@ -0,0 +1,188 @@ + + + EvaluationTool + + + + 0 + 0 + 869 + 514 + + + + Evaluate Traces + + + + + + + + + 1 + 0 + + + + + + + + + 5 + 0 + + + + 1 + + + + + 0 + 0 + 702 + 432 + + + + Test + + + + + + + + + 1 + + + + + + + + + + Run tests + + + + + + + + + + 0 + 30 + + + + + + + + Message: + + + + + + + + + + + + + + + + + + 0 + 0 + 702 + 432 + + + + Calculate Metrics + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Calculate metrics + + + + + + + Export to CSV + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + TestLight + QWidget +
presentation/util/testlight.h
+ 1 +
+ + TraceTestTreeWidget + QTreeWidget +
presentation/tracetesttreewidget.h
+
+ + TraceMetricTreeWidget + QTreeWidget +
presentation/tracemetrictreewidget.h
+
+
+ + +
diff --git a/analyzer/analyzer/gototimedialog.cpp b/analyzer/analyzer/gototimedialog.cpp new file mode 100644 index 00000000..33d2df98 --- /dev/null +++ b/analyzer/analyzer/gototimedialog.cpp @@ -0,0 +1,29 @@ +#include "gototimedialog.h" +#include "ui_gototimedialog.h" +#include + +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"); + } +} diff --git a/analyzer/analyzer/gototimedialog.h b/analyzer/analyzer/gototimedialog.h new file mode 100644 index 00000000..737e7eb0 --- /dev/null +++ b/analyzer/analyzer/gototimedialog.h @@ -0,0 +1,30 @@ +#ifndef GOTOTIMEDIALOG_H +#define GOTOTIMEDIALOG_H +#include + + + +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 diff --git a/analyzer/analyzer/gototimedialog.ui b/analyzer/analyzer/gototimedialog.ui new file mode 100644 index 00000000..f9243552 --- /dev/null +++ b/analyzer/analyzer/gototimedialog.ui @@ -0,0 +1,38 @@ + + + GoToTimeDialog + + + + 0 + 0 + 395 + 45 + + + + Go to time + + + + + + + + + ns + + + + + + + Ok + + + + + + + + diff --git a/analyzer/analyzer/main.cpp b/analyzer/analyzer/main.cpp new file mode 100644 index 00000000..53fea5ea --- /dev/null +++ b/analyzer/analyzer/main.cpp @@ -0,0 +1,61 @@ +#include "traceanalyzer.h" +#include +#include +#include +#include + +#include +#include +using namespace std; + +int main(int argc, char *argv[]) +{ + cout << argv[0] << std::endl; + QApplication a(argc, argv); + + if(argc > 1) + { + QSet arguments; + for(int i = 1;i 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(); + } + +} + + diff --git a/analyzer/analyzer/mainwindow.cpp b/analyzer/analyzer/mainwindow.cpp new file mode 100644 index 00000000..0e2df84c --- /dev/null +++ b/analyzer/analyzer/mainwindow.cpp @@ -0,0 +1,39 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "traceDB.h" +#include "xmldeserializer.h" +#include + +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; +} diff --git a/analyzer/analyzer/mainwindow.h b/analyzer/analyzer/mainwindow.h new file mode 100644 index 00000000..e3a3ef6c --- /dev/null +++ b/analyzer/analyzer/mainwindow.h @@ -0,0 +1,35 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +#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 phases; + QHash transactions; + +}; + +#endif // MAINWINDOW_H diff --git a/analyzer/analyzer/markerplotitem.cpp b/analyzer/analyzer/markerplotitem.cpp new file mode 100644 index 00000000..026b72cb --- /dev/null +++ b/analyzer/analyzer/markerplotitem.cpp @@ -0,0 +1,13 @@ +#include "markerplotitem.h" +#include "tracedrawing.h" +#include + +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); +} diff --git a/analyzer/analyzer/markerplotitem.h b/analyzer/analyzer/markerplotitem.h new file mode 100644 index 00000000..2cadd216 --- /dev/null +++ b/analyzer/analyzer/markerplotitem.h @@ -0,0 +1,20 @@ +#ifndef MARKERPLOTITEM_H +#define MARKERPLOTITEM_H +#include +#include + +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 diff --git a/analyzer/analyzer/paths.pro b/analyzer/analyzer/paths.pro new file mode 100644 index 00000000..4502b6fe --- /dev/null +++ b/analyzer/analyzer/paths.pro @@ -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 +} diff --git a/analyzer/analyzer/preferences.ui b/analyzer/analyzer/preferences.ui new file mode 100644 index 00000000..7e34a428 --- /dev/null +++ b/analyzer/analyzer/preferences.ui @@ -0,0 +1,61 @@ + + + Preferences + + + + 0 + 0 + 400 + 300 + + + + Preferences + + + + + 10 + 10 + 291 + 101 + + + + Color-Grouping: + + + + 0 + + + QLayout::SetMaximumSize + + + + + Phase-Type + + + + + + + Transaction + + + + + + + Thread + + + + + + + + + diff --git a/analyzer/analyzer/presentation/commenttreewidget.cpp b/analyzer/analyzer/presentation/commenttreewidget.cpp new file mode 100644 index 00000000..3cbcff55 --- /dev/null +++ b/analyzer/analyzer/presentation/commenttreewidget.cpp @@ -0,0 +1,65 @@ +#include "commenttreewidget.h" +#include +#include +#include + +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(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(item); + navigator->removeCommentAtTime(commentItem->Time()); + } + } +} + + +CommentTreeWidget::CommentTreeItem::CommentTreeItem(QTreeWidget *parent, const Comment &comment):QTreeWidgetItem(parent),comment(comment) +{ + this->setText(0,formatTraceTimePretty(comment.Time())); + this->setText(1,comment.Text()); +} diff --git a/analyzer/analyzer/presentation/commenttreewidget.h b/analyzer/analyzer/presentation/commenttreewidget.h new file mode 100644 index 00000000..89799740 --- /dev/null +++ b/analyzer/analyzer/presentation/commenttreewidget.h @@ -0,0 +1,38 @@ +#ifndef COMMENTTREEWIDGET_H +#define COMMENTTREEWIDGET_H +#include +#include +#include +#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 diff --git a/analyzer/analyzer/presentation/debugmessagetreewidget.cpp b/analyzer/analyzer/presentation/debugmessagetreewidget.cpp new file mode 100644 index 00000000..01a58ea5 --- /dev/null +++ b/analyzer/analyzer/presentation/debugmessagetreewidget.cpp @@ -0,0 +1,90 @@ +#include "debugmessagetreewidget.h" +#include +#include + +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& comments) +{ + clear(); + if(comments.empty()) + return; + + traceTime currentTime = -1; + for(Comment comment: comments) + { + if(currentTime != comment.Time()) + { + addTopLevelItem(new QTreeWidgetItem({formatTraceTimePretty(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)); + } +} + + diff --git a/analyzer/analyzer/presentation/debugmessagetreewidget.h b/analyzer/analyzer/presentation/debugmessagetreewidget.h new file mode 100644 index 00000000..7a0e6cc8 --- /dev/null +++ b/analyzer/analyzer/presentation/debugmessagetreewidget.h @@ -0,0 +1,37 @@ +#ifndef DEBUGMESSAGELISTWIDGET_H +#define DEBUGMESSAGELISTWIDGET_H +#include +#include +#include +#include +#include +#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& 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 diff --git a/analyzer/analyzer/presentation/pornotracescroller.cpp b/analyzer/analyzer/presentation/pornotracescroller.cpp new file mode 100644 index 00000000..4321da61 --- /dev/null +++ b/analyzer/analyzer/presentation/pornotracescroller.cpp @@ -0,0 +1,238 @@ +#include +#include +#include +#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 (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(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(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(event); + traceTime time = invTransform(xBottom, mouseEvent->x()); + navigator->navigateToTime(time); + return true; + } + case QEvent::MouseButtonPress: + { + QMouseEvent *mouseEvent = static_cast(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(invTransform(xBottom, mouseEvent->x()))); + return true; + } + } + case QEvent::MouseButtonRelease: + { + QMouseEvent *mouseEvent = static_cast(event); + if(mouseEvent->button() == Qt::LeftButton) + { + clipDragged = false; + leftMousePressed = false; + canvas()->setCursor(Qt::ArrowCursor); + return true; + } + } + case QEvent::MouseMove: + { + QMouseEvent *mouseEvent = static_cast(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((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; +} diff --git a/analyzer/analyzer/presentation/pornotracescroller.h b/analyzer/analyzer/presentation/pornotracescroller.h new file mode 100644 index 00000000..ec552ff3 --- /dev/null +++ b/analyzer/analyzer/presentation/pornotracescroller.h @@ -0,0 +1,46 @@ +#ifndef PORNOTRACESCROLLER_H +#define PORNOTRACESCROLLER_H + +#include +#include +#include +#include "presentation/tracenavigator.h" +#include "traceplot.h" + + +class PornoTraceScroller : public QwtPlot +{ +Q_OBJECT +private: + std::vector> 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 diff --git a/analyzer/analyzer/presentation/selectedtransactiontreewidget.cpp b/analyzer/analyzer/presentation/selectedtransactiontreewidget.cpp new file mode 100644 index 00000000..95a20a83 --- /dev/null +++ b/analyzer/analyzer/presentation/selectedtransactiontreewidget.cpp @@ -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())); +} diff --git a/analyzer/analyzer/presentation/selectedtransactiontreewidget.h b/analyzer/analyzer/presentation/selectedtransactiontreewidget.h new file mode 100644 index 00000000..3621d647 --- /dev/null +++ b/analyzer/analyzer/presentation/selectedtransactiontreewidget.h @@ -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 diff --git a/analyzer/analyzer/presentation/tracePlotMouseLabel.cpp b/analyzer/analyzer/presentation/tracePlotMouseLabel.cpp new file mode 100644 index 00000000..06209dc2 --- /dev/null +++ b/analyzer/analyzer/presentation/tracePlotMouseLabel.cpp @@ -0,0 +1,22 @@ +#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(traceplot->invTransform(traceplot->xBottom, point.x())); + return QwtText(formatTraceTimePretty(alignToClk(mouseTime,clkPeriod))); + } + else if(mode == MouseLabelMode::Timedifference) + { + long long numberOfClockCovered = timeDifferenceSpan.timeCovered()/clkPeriod; + QString suffix = (numberOfClockCovered != 1) ? QString(" clks") : QString(" clk"); + return(QwtText(QString::number(numberOfClockCovered) + suffix)); + } +} diff --git a/analyzer/analyzer/presentation/tracePlotMouseLabel.h b/analyzer/analyzer/presentation/tracePlotMouseLabel.h new file mode 100644 index 00000000..9043745e --- /dev/null +++ b/analyzer/analyzer/presentation/tracePlotMouseLabel.h @@ -0,0 +1,28 @@ +#ifndef TRACEPLOTPICKER_H +#define TRACEPLOTPICKER_H + +#include +#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()), + traceplot(traceplot),clkPeriod(clkPeriod), timeDifferenceSpan(timeDifferenceSpan), mode(MouseLabelMode::AbsoluteTime){} + + void setMode(MouseLabelMode mode); +protected: + virtual QwtText trackerText(const QPoint &point) const; + +private: + MouseLabelMode mode; + TracePlot* traceplot; + Timespan& timeDifferenceSpan; + unsigned int clkPeriod; +}; + +#endif // TRACEPLOTPICKER_H diff --git a/analyzer/analyzer/presentation/tracedrawing.cpp b/analyzer/analyzer/presentation/tracedrawing.cpp new file mode 100644 index 00000000..ab2847f6 --- /dev/null +++ b/analyzer/analyzer/presentation/tracedrawing.cpp @@ -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(canvasRect.top())); + QPoint P2(xPos,static_cast(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); +} diff --git a/analyzer/analyzer/presentation/tracedrawing.h b/analyzer/analyzer/presentation/tracedrawing.h new file mode 100644 index 00000000..2ffe3318 --- /dev/null +++ b/analyzer/analyzer/presentation/tracedrawing.h @@ -0,0 +1,17 @@ +#ifndef TRACEDRAWING_H +#define TRACEDRAWING_H + +#include +#include +#include +#include + +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 diff --git a/analyzer/analyzer/presentation/tracedrawingproperties.h b/analyzer/analyzer/presentation/tracedrawingproperties.h new file mode 100644 index 00000000..2d340f91 --- /dev/null +++ b/analyzer/analyzer/presentation/tracedrawingproperties.h @@ -0,0 +1,43 @@ +#ifndef TRACECOLLECTIONDRAWINGPROPERTIES_H +#define TRACECOLLECTIONDRAWINGPROPERTIES_H +#include +#include +#include +#include +#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 getLabels() const + { + QHash result; + for(unsigned int i=0; i +#include "businessObjects/tracecalculatedmetrics.h" + + +class TraceMetricTreeWidget : public QTreeWidget +{ + Q_OBJECT +public: + TraceMetricTreeWidget(QWidget *parent = 0); + void addTraceMetricResults(const TraceCalculatedMetrics& result); + +}; + +#endif // TRACEMETRICTREEWIDGET_H diff --git a/analyzer/analyzer/presentation/tracenavigator.cpp b/analyzer/analyzer/presentation/tracenavigator.cpp new file mode 100644 index 00000000..74d11733 --- /dev/null +++ b/analyzer/analyzer/presentation/tracenavigator.cpp @@ -0,0 +1,251 @@ +#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 commentsToInsert; + for(const auto& pair: comments) + { + commentsToInsert.push_back(pair.second); + } + + traceFile.updateComments(commentsToInsert); + //TODO : reinsert file description logic + //traceFile.updateFileDescription(traceFile.getGeneralInfo().Description()); + changesToCommitExist = false; +} + +void TraceNavigator::getCommentsFromDB() +{ + for(const Comment& comment: traceFile.getComments()) + { + comments.emplace(comment.Time(),comment); + } +} + +void TraceNavigator::setFileDescripton(const QString &description) +{ + //TODO : reinsert file description logic + changesToCommitExist = true; +} + +void TraceNavigator::refreshData() +{ + traceFile.refreshData(); + clearSelectedTransactions(); + navigateToTime(currentTraceTime); +} + +/* Transaction Selection + * + * + */ + +void TraceNavigator::addSelectedTransactions(const vector>& transactions) +{ + for(const auto transaction : transactions) + { + selectedTransactions.push_back(transaction); + } + Q_EMIT selectedTransactionsChanged(); +} + +void TraceNavigator::addSelectedTransaction(const shared_ptr &transaction) +{ + selectedTransactions.push_back(transaction); + Q_EMIT selectedTransactionsChanged(); +} + +void TraceNavigator::addSelectedTransaction(ID id) +{ + shared_ptr 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) +{ + 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 nextRefresh; + + if(!SelectedTransactions().empty()) + nextRefresh = traceFile.getNextRefresh(SelectedTransactions().front()->Id()); + else + nextRefresh = traceFile.getNextRefresh(0); + + if(nextRefresh) + selectTransaction(nextRefresh); +} + +void TraceNavigator::selectNextActivate() +{ + shared_ptr nextActivate; + + if(!SelectedTransactions().empty()) + nextActivate = traceFile.getNextActivate(SelectedTransactions().front()->Id()); + else + nextActivate = traceFile.getNextActivate(0); + + if(nextActivate) + selectTransaction(nextActivate); +} + +void TraceNavigator::selectNextPrecharge() +{ + shared_ptr 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) 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); +} diff --git a/analyzer/analyzer/presentation/tracenavigator.h b/analyzer/analyzer/presentation/tracenavigator.h new file mode 100644 index 00000000..aad497db --- /dev/null +++ b/analyzer/analyzer/presentation/tracenavigator.h @@ -0,0 +1,82 @@ +#ifndef TRACENAVIGATOR_H +#define TRACENAVIGATOR_H +#include +#include +#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; + +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); + void selectNextTransaction(); + void selectPreviousTransaction(); + void selectLastTransaction(); + void selectFirstTransaction(); + void selectNextRefresh(); + void selectNextActivate(); + void selectNextPrecharge(); + + void addSelectedTransactions(const std::vector>& transactions); + const std::vector>& SelectedTransactions(){return selectedTransactions;} + void addSelectedTransaction(const std::shared_ptr &Transaction); + void addSelectedTransaction(ID id); + void clearSelectedTransactions(); + bool hasSelectedTransactions(); + Timespan getSpanCoveredBySelectedTransaction(); + + bool transactionIsSelected(ID id) const; + bool transactionIsSelected(const std::shared_ptr &Transaction) const; + + void insertComment(const Comment& comment); + const CommentMap& getComments(){return comments;} + void removeCommentAtTime(traceTime time); + + void setFileDescripton(const QString& text); + 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> selectedTransactions; + CommentMap comments; + void getCommentsFromDB(); + bool changesToCommitExist; + +}; + +#endif // TRACENAVIGATOR_H diff --git a/analyzer/analyzer/presentation/traceplot.cpp b/analyzer/analyzer/presentation/traceplot.cpp new file mode 100644 index 00000000..3127aea9 --- /dev/null +++ b/analyzer/analyzer/presentation/traceplot.cpp @@ -0,0 +1,546 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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(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 ") + formatTraceTimePretty(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(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(event); + traceTime zoomCenter = static_cast(this->invTransform(xBottom, wheelEvent->x())); + + (wheelEvent->delta() > 0) ? zoomIn(zoomCenter) : zoomOut(zoomCenter); + + return true; + } + case QEvent::MouseButtonPress: + { + QMouseEvent *mouseEvent = static_cast(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(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(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> 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); +} + + diff --git a/analyzer/analyzer/presentation/traceplot.h b/analyzer/analyzer/presentation/traceplot.h new file mode 100644 index 00000000..4d8f601d --- /dev/null +++ b/analyzer/analyzer/presentation/traceplot.h @@ -0,0 +1,151 @@ +#ifndef TRACEPLOT_H +#define TRACEPLOT_H +#include +#include +#include +#include +#include +#include +#include +#include +#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> 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 diff --git a/analyzer/analyzer/presentation/traceplotitem.cpp b/analyzer/analyzer/presentation/traceplotitem.cpp new file mode 100644 index 00000000..7c3524f1 --- /dev/null +++ b/analyzer/analyzer/presentation/traceplotitem.cpp @@ -0,0 +1,36 @@ +#include "traceplotitem.h" +#include "tracedrawing.h" +#include "util/colorgenerator.h" +#include +#include +#include +#include +#include + +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> TracePlotItem::getSelectedTransactions(traceTime time, double yVal) +{ + vector> result; + + for(const auto &transaction : transactions) + { + if(transaction->isSelected(time,yVal,drawingProperties)) + result.push_back(transaction); + } + + return result; +} diff --git a/analyzer/analyzer/presentation/traceplotitem.h b/analyzer/analyzer/presentation/traceplotitem.h new file mode 100644 index 00000000..d2d06d4d --- /dev/null +++ b/analyzer/analyzer/presentation/traceplotitem.h @@ -0,0 +1,32 @@ +#ifndef TRACEPLOTITEM_H +#define TRACEPLOTITEM_H + +#include +#include +#include +#include +#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> &transactions; + const TraceNavigator& navigator; + const TraceDrawingProperties &drawingProperties; + +public: + TracePlotItem(const std::vector> &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> getSelectedTransactions(traceTime time,double yVal); + +}; + +#endif // TRACEPLOTITEM_H + diff --git a/analyzer/analyzer/presentation/tracetesttreewidget.cpp b/analyzer/analyzer/presentation/tracetesttreewidget.cpp new file mode 100644 index 00000000..1229103f --- /dev/null +++ b/analyzer/analyzer/presentation/tracetesttreewidget.cpp @@ -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(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(); +} diff --git a/analyzer/analyzer/presentation/tracetesttreewidget.h b/analyzer/analyzer/presentation/tracetesttreewidget.h new file mode 100644 index 00000000..4a5f069a --- /dev/null +++ b/analyzer/analyzer/presentation/tracetesttreewidget.h @@ -0,0 +1,31 @@ +#ifndef TRACETESTTREEWIDGET_H +#define TRACETESTTREEWIDGET_H +#include +#include + +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 diff --git a/analyzer/analyzer/presentation/transactiontreewidget.cpp b/analyzer/analyzer/presentation/transactiontreewidget.cpp new file mode 100644 index 00000000..6c686eb8 --- /dev/null +++ b/analyzer/analyzer/presentation/transactiontreewidget.cpp @@ -0,0 +1,94 @@ +#include "transactiontreewidget.h" +#include "data/tracedb.h" +#include +#include +#include + +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) +{ + 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(selectedItems().at(0)); + navigator->selectTransaction(item->Id()); + } + } +} + +TransactionTreeWidget::TransactionTreeItem::TransactionTreeItem(QTreeWidget *parent, const shared_ptr &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", formatTraceTimePretty(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 : transaction->Phases()) + { + AppendPhase(phasesNode, *phase); + } +} + +void TransactionTreeWidget::TransactionTreeItem::AppendPhase(QTreeWidgetItem *parent, const Phase &phase) +{ + QTreeWidgetItem *node = new QTreeWidgetItem(parent); + node->setText(0, phase.Name() + QString(" [") + QString::number(phase.Id()) + QString("]")); + + AppendTimespan(node, phase.Span()); +} + +void TransactionTreeWidget::TransactionTreeItem::AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan) +{ + parent->setText(1, formatTraceTimePretty(timespan.Begin())); + parent->setText(2, formatTraceTimePretty(timespan.End())); +} diff --git a/analyzer/analyzer/presentation/transactiontreewidget.h b/analyzer/analyzer/presentation/transactiontreewidget.h new file mode 100644 index 00000000..2dbd51fc --- /dev/null +++ b/analyzer/analyzer/presentation/transactiontreewidget.h @@ -0,0 +1,48 @@ +#ifndef TRANSACTIONTREEWIDGET_H +#define TRANSACTIONTREEWIDGET_H + +#include +#include "tracenavigator.h" +#include +#include + +class TransactionTreeWidget : public QTreeWidget +{ + + Q_OBJECT + +public: + TransactionTreeWidget(QWidget *parent); + + void AppendTransaction(const std::shared_ptr &transaction); + virtual void init(TraceNavigator *navigator); + +public Q_SLOTS: + void ContextMenuRequested(QPoint point); + +protected: + TraceNavigator *navigator; + +private: + bool isInitialized; + void AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan); + void AppendPhase(QTreeWidgetItem *parent, const Phase &phase); + QAction* goToTransaction; + + class TransactionTreeItem : public QTreeWidgetItem + { + public: + static constexpr int transactionTreeItemType = 1001; + TransactionTreeItem(QTreeWidget *parent, const std::shared_ptr &trans); + ID Id(){return id;} + private: + ID id; + void AppendTimespan(QTreeWidgetItem *parent, const Timespan ×pan); + void AppendPhase(QTreeWidgetItem *parent, const Phase &phase); + }; + + + +}; + +#endif // TRANSACTIONTREEWIDGET_H diff --git a/analyzer/analyzer/presentation/util/clkgrid.cpp b/analyzer/analyzer/presentation/util/clkgrid.cpp new file mode 100644 index 00000000..9cd7a80c --- /dev/null +++ b/analyzer/analyzer/presentation/util/clkgrid.cpp @@ -0,0 +1,29 @@ +#include "clkgrid.h" +#include + +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( min / clkPeriod ) * clkPeriod; + QList ticks; + for ( double tick = min; tick <= max; tick += clkPeriod ) + ticks += tick; + + scaleDiv.setTicks( QwtScaleDiv::MajorTick, ticks ); + + } + + QwtPlotGrid::updateScaleDiv( scaleDiv, yMap ); + } diff --git a/analyzer/analyzer/presentation/util/clkgrid.h b/analyzer/analyzer/presentation/util/clkgrid.h new file mode 100644 index 00000000..82f25219 --- /dev/null +++ b/analyzer/analyzer/presentation/util/clkgrid.h @@ -0,0 +1,18 @@ +#ifndef CLKGRID_H +#define CLKGRID_H + +#include +#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 diff --git a/analyzer/analyzer/presentation/util/colorgenerator.cpp b/analyzer/analyzer/presentation/util/colorgenerator.cpp new file mode 100644 index 00000000..63184759 --- /dev/null +++ b/analyzer/analyzer/presentation/util/colorgenerator.cpp @@ -0,0 +1,31 @@ +#include "colorgenerator.h" +#include +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; +} + diff --git a/analyzer/analyzer/presentation/util/colorgenerator.h b/analyzer/analyzer/presentation/util/colorgenerator.h new file mode 100644 index 00000000..37a4d9a7 --- /dev/null +++ b/analyzer/analyzer/presentation/util/colorgenerator.h @@ -0,0 +1,21 @@ +#ifndef COLORGENERATOR_H +#define COLORGENERATOR_H + +#include +#include + +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 diff --git a/analyzer/analyzer/presentation/util/customlabelscaledraw.h b/analyzer/analyzer/presentation/util/customlabelscaledraw.h new file mode 100644 index 00000000..1da4521d --- /dev/null +++ b/analyzer/analyzer/presentation/util/customlabelscaledraw.h @@ -0,0 +1,20 @@ +#ifndef CUSTOMLABELSCALEDRAW_H +#define CUSTOMLABELSCALEDRAW_H +#include +#include +#include + +class CustomLabelScaleDraw : public QwtScaleDraw +{ +private: + QHash labels; + +public: + CustomLabelScaleDraw(QHash labels): labels(labels){} + virtual QwtText label(double v) const + { + return QwtText(labels[static_cast(v)]); + } +}; + +#endif // CUSTOMLABELSCALEDRAW_H diff --git a/analyzer/analyzer/presentation/util/engineeringScaleDraw.h b/analyzer/analyzer/presentation/util/engineeringScaleDraw.h new file mode 100644 index 00000000..365c698d --- /dev/null +++ b/analyzer/analyzer/presentation/util/engineeringScaleDraw.h @@ -0,0 +1,16 @@ +#ifndef ENGINEERINGSCALEDRAW_H +#define ENGINEERINGSCALEDRAW_H +#include +#include +#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 diff --git a/analyzer/analyzer/presentation/util/testlight.cpp b/analyzer/analyzer/presentation/util/testlight.cpp new file mode 100644 index 00000000..361c5691 --- /dev/null +++ b/analyzer/analyzer/presentation/util/testlight.cpp @@ -0,0 +1,33 @@ +#include "testlight.h" +#include + +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()); +} + diff --git a/analyzer/analyzer/presentation/util/testlight.h b/analyzer/analyzer/presentation/util/testlight.h new file mode 100644 index 00000000..325105a8 --- /dev/null +++ b/analyzer/analyzer/presentation/util/testlight.h @@ -0,0 +1,23 @@ +#ifndef TESTLIGHT_H +#define TESTLIGHT_H +#include +#include +#include + +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 diff --git a/analyzer/analyzer/queryeditor.cpp b/analyzer/analyzer/queryeditor.cpp new file mode 100644 index 00000000..a743471e --- /dev/null +++ b/analyzer/analyzer/queryeditor.cpp @@ -0,0 +1,40 @@ +#include "queryeditor.h" +#include "ui_queryeditor.h" +#include +#include + +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> 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()); + } +} diff --git a/analyzer/analyzer/queryeditor.h b/analyzer/analyzer/queryeditor.h new file mode 100644 index 00000000..107272e7 --- /dev/null +++ b/analyzer/analyzer/queryeditor.h @@ -0,0 +1,30 @@ +#ifndef QUERYEDITOR_H +#define QUERYEDITOR_H + +#include +#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 diff --git a/analyzer/analyzer/queryeditor.ui b/analyzer/analyzer/queryeditor.ui new file mode 100644 index 00000000..60bf1ddf --- /dev/null +++ b/analyzer/analyzer/queryeditor.ui @@ -0,0 +1,80 @@ + + + QueryEditor + + + + 0 + 0 + 667 + 451 + + + + Form + + + + + + + + false + + + + 0 + 1 + + + + true + + + + + + + + 0 + 1 + + + + + + + + Execute query + + + + + + + + 0 + 5 + + + + + 1 + + + + + + + + + + + TransactionTreeWidget + QTreeWidget +
presentation/transactiontreewidget.h
+
+
+ + +
diff --git a/analyzer/analyzer/schedulerwrapper.h b/analyzer/analyzer/schedulerwrapper.h new file mode 100644 index 00000000..939fbe39 --- /dev/null +++ b/analyzer/analyzer/schedulerwrapper.h @@ -0,0 +1,33 @@ +#ifndef SCHEDULERWRAPPER_H +#define SCHEDULERWRAPPER_H + +#include +#include +#include +#include +#include + +struct SchedulerWrapper : public sc_module +{ + tlm_utils::simple_initiator_socket iSocket; + tlm_utils::simple_target_socket tSocket; + + SC_HAS_PROCESS(SchedulerWrapper); + + SchedulerWrapper(sc_module_name name); + +private: + tlm_utils::peq_with_cb_and_phase 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 + + diff --git a/analyzer/analyzer/thirdParty/eng_formant.cpp b/analyzer/analyzer/thirdParty/eng_formant.cpp new file mode 100644 index 00000000..eba663b8 --- /dev/null +++ b/analyzer/analyzer/thirdParty/eng_formant.cpp @@ -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 +#include +#include + +#include +#include +#include + +/* + * 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( 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 +long lrint( T const x ) +{ + return static_cast( 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 diff --git a/analyzer/analyzer/thirdParty/eng_format.h b/analyzer/analyzer/thirdParty/eng_format.h new file mode 100644 index 00000000..1e528057 --- /dev/null +++ b/analyzer/analyzer/thirdParty/eng_format.h @@ -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 + +/** + * 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 diff --git a/analyzer/analyzer/traceAnalyzer.pro b/analyzer/analyzer/traceAnalyzer.pro new file mode 100644 index 00000000..0c58af9a --- /dev/null +++ b/analyzer/analyzer/traceAnalyzer.pro @@ -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 diff --git a/analyzer/analyzer/traceanalyzer.cpp b/analyzer/analyzer/traceanalyzer.cpp new file mode 100644 index 00000000..771b33eb --- /dev/null +++ b/analyzer/analyzer/traceanalyzer.cpp @@ -0,0 +1,109 @@ +#include "traceanalyzer.h" +#include "ui_traceanalyzer.h" +#include "tracefiletab.h" +#include +#include +#include +#include "QMessageBox" +#include + +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 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(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()); + +} diff --git a/analyzer/analyzer/traceanalyzer.h b/analyzer/analyzer/traceanalyzer.h new file mode 100644 index 00000000..5104da03 --- /dev/null +++ b/analyzer/analyzer/traceanalyzer.h @@ -0,0 +1,52 @@ +#ifndef TRACEANALYZER_H +#define TRACEANALYZER_H + +#include +#include +#include +#include +#include +#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 paths, StartupOption option, QWidget *parent = 0); + + ~TraceAnalyzer(); + EvaluationTool evaluationTool; + + void setUpStatusBar(); + void setUpGui(); + +private: + void openTracefile(const QString &path); + QLabel *statusLabel; + QSet 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 diff --git a/analyzer/analyzer/traceanalyzer.ui b/analyzer/analyzer/traceanalyzer.ui new file mode 100644 index 00000000..d99934c7 --- /dev/null +++ b/analyzer/analyzer/traceanalyzer.ui @@ -0,0 +1,126 @@ + + + TraceAnalyzer + + + + 0 + 0 + 800 + 600 + + + + Trace Analyzer + + + + + + + 0 + + + true + + + true + + + true + + + + Tab 1 + + + + + Tab 2 + + + + + + + + + + 0 + 0 + 800 + 25 + + + + + File + + + + + + + + + + Help + + + + + + + + + + + Open + + + Ctrl+O + + + + + Close all + + + + + Info + + + + + About + + + + + Preferences + + + Ctrl+P + + + + + Test + + + Ctrl+T + + + + + Metrics + + + Ctrl+M + + + + + + diff --git a/analyzer/analyzer/tracefiletab.cpp b/analyzer/analyzer/tracefiletab.cpp new file mode 100644 index 00000000..fde96b89 --- /dev/null +++ b/analyzer/analyzer/tracefiletab.cpp @@ -0,0 +1,60 @@ +#include "tracefiletab.h" +#include "ui_tracefiletab.h" +#include "queryeditor.h" +#include "QFileInfo" +#include "qmessagebox.h" +#include +#include + +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->setFileDescripton(ui->fileDescriptionEdit->toPlainText()); + 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(); +} + + + + + diff --git a/analyzer/analyzer/tracefiletab.h b/analyzer/analyzer/tracefiletab.h new file mode 100644 index 00000000..da66a1ec --- /dev/null +++ b/analyzer/analyzer/tracefiletab.h @@ -0,0 +1,43 @@ +#ifndef TRACEFILETAB_H +#define TRACEFILETAB_H + +#include +#include +#include +#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 diff --git a/analyzer/analyzer/tracefiletab.ui b/analyzer/analyzer/tracefiletab.ui new file mode 100644 index 00000000..e3d18d6f --- /dev/null +++ b/analyzer/analyzer/tracefiletab.ui @@ -0,0 +1,182 @@ + + + TraceFileTab + + + + 0 + 0 + 1235 + 937 + + + + Form + + + + + + + + + + + 3 + 4 + + + + + 0 + 0 + + + + Qt::StrongFocus + + + + + + + + 4 + 1 + + + + + 0 + 150 + + + + + + + + + + + + + 3 + 3 + + + + + 300 + 0 + + + + + 16777215 + 16777215 + + + + true + + + false + + + false + + + 0 + + + true + + + + + + + + 2 + 1 + + + + + 300 + 0 + + + + + 16777215 + 16777215 + + + + + 1 + + + + + + + + true + + + + 2 + 1 + + + + + 300 + 0 + + + + + 16777215 + 16777215 + + + + true + + + + + + + + + + + + TracePlot + QListView +
presentation/traceplot.h
+
+ + PornoTraceScroller + QListView +
presentation/pornotracescroller.h
+
+ + CommentTreeWidget + QTreeWidget +
presentation/commenttreewidget.h
+
+ + SelectedTransactionTreeWidget + QTreeWidget +
presentation/selectedtransactiontreewidget.h
+
+
+ + +
diff --git a/dram/dramSys/dramSys.pro b/dram/dramSys/dramSys.pro index 65291f71..98ac915e 100644 --- a/dram/dramSys/dramSys.pro +++ b/dram/dramSys/dramSys.pro @@ -1,4 +1,4 @@ -TEMPLATE = app + TEMPLATE = app CONFIG += console CONFIG -= app_bundle CONFIG -= qt