Switch to pybind11
With the switch to pybind11, the complexity of the Python integration in the TraceAnalyzer can be greatly reduced. The new code is much easier to understand and fixes a number of bugs regarding the Python integration.
This commit is contained in:
@@ -44,7 +44,14 @@ file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
|
|||||||
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
|
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
|
||||||
|
|
||||||
# Add Python3 Dependency:
|
# Add Python3 Dependency:
|
||||||
find_package(Python3 COMPONENTS Development)
|
find_package(Python3 COMPONENTS Development Interpreter)
|
||||||
|
|
||||||
|
FetchContent_Declare(
|
||||||
|
pybind11
|
||||||
|
URL https://github.com/pybind/pybind11/archive/refs/tags/v2.10.4.zip
|
||||||
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(pybind11)
|
||||||
|
|
||||||
# Add QWT Dependency:
|
# Add QWT Dependency:
|
||||||
find_library(QWT_LIBRARY NAMES "qwt" "qwt-qt5" PATHS
|
find_library(QWT_LIBRARY NAMES "qwt" "qwt-qt5" PATHS
|
||||||
@@ -74,11 +81,10 @@ add_executable(TraceAnalyzer ${SOURCE_FILES} ${HEADER_FILES})
|
|||||||
target_include_directories(TraceAnalyzer
|
target_include_directories(TraceAnalyzer
|
||||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
PRIVATE ${QWT_INCLUDE_DIRS}
|
PRIVATE ${QWT_INCLUDE_DIRS}
|
||||||
PRIVATE ${Python3_INCLUDE_DIRS}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(TraceAnalyzer
|
target_link_libraries(TraceAnalyzer
|
||||||
PRIVATE ${Python3_LIBRARIES}
|
PRIVATE pybind11::embed
|
||||||
PRIVATE ${QWT_LIBRARY}
|
PRIVATE ${QWT_LIBRARY}
|
||||||
PRIVATE Qt5::Widgets
|
PRIVATE Qt5::Widgets
|
||||||
PRIVATE Qt5::Sql
|
PRIVATE Qt5::Sql
|
||||||
@@ -86,5 +92,12 @@ target_link_libraries(TraceAnalyzer
|
|||||||
PRIVATE DRAMSys::config
|
PRIVATE DRAMSys::config
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(DRAMSYS_TRACEANALYZER_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
target_compile_definitions(${PROJECT_NAME}
|
||||||
|
PUBLIC
|
||||||
|
DRAMSYS_TRACEANALYZER_DIR="${DRAMSYS_TRACEANALYZER_DIR}"
|
||||||
|
)
|
||||||
|
|
||||||
build_source_group()
|
build_source_group()
|
||||||
diagnostics_print(${PROJECT_NAME})
|
diagnostics_print(${PROJECT_NAME})
|
||||||
|
|||||||
@@ -1,2 +1,13 @@
|
|||||||
dram.vp.scheduler
|
## TraceAnalyzer
|
||||||
=================
|
### Python Dependencies
|
||||||
|
The used Python dependencies of this project include:
|
||||||
|
- matplotlib
|
||||||
|
- numpy
|
||||||
|
- pyvcd
|
||||||
|
- tqdm
|
||||||
|
|
||||||
|
To install all required packages, a `requirements.txt` file is provided, which can be found in `scripts/requirements.txt`.
|
||||||
|
Install the packages using this command:
|
||||||
|
```
|
||||||
|
python3 -m pip install -r scripts/requirements.txt
|
||||||
|
```
|
||||||
|
|||||||
@@ -33,30 +33,17 @@
|
|||||||
* Janik Schlemminger
|
* Janik Schlemminger
|
||||||
* Robert Gernhardt
|
* Robert Gernhardt
|
||||||
* Matthias Jung
|
* Matthias Jung
|
||||||
|
* Derek Christ
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef METRIC_H
|
#ifndef METRIC_H
|
||||||
#define METRIC_H
|
#define METRIC_H
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
class CalculatedMetric
|
struct CalculatedMetric
|
||||||
{
|
{
|
||||||
public:
|
std::string name;
|
||||||
CalculatedMetric(QString name, double value): name(name), value(value) {}
|
|
||||||
QString getName()
|
|
||||||
{
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
double getValue()
|
|
||||||
{
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString name;
|
|
||||||
double value;
|
double value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // METRIC_H
|
#endif // METRIC_H
|
||||||
|
|||||||
@@ -41,205 +41,78 @@
|
|||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <QFileInfo>
|
#include <pybind11/pybind11.h>
|
||||||
#include <QDebug>
|
#include <pybind11/stl.h>
|
||||||
#include <QApplication>
|
|
||||||
|
|
||||||
PythonCaller::PythonCaller() :
|
std::string PythonCaller::generatePlots(std::string_view pathToTrace)
|
||||||
metricModuleName("metrics"),
|
|
||||||
metricFunctionName("calculateMetrics"),
|
|
||||||
getMetricFunctionName("getMetrics"),
|
|
||||||
|
|
||||||
pathToScripts(QApplication::applicationDirPath().toStdString() +
|
|
||||||
"/../../extensions/apps/traceAnalyzer/scripts/"),
|
|
||||||
plotsModuleName("plots"),
|
|
||||||
plotsFunctionName("generatePlots"),
|
|
||||||
checkDependenciesModuleName("checkDependencies"),
|
|
||||||
vcdExportModuleName("vcdExport"),
|
|
||||||
vcdExportFunctionName("dumpVcd"),
|
|
||||||
vcdExportDependenciesFunctionName("checkVcdExport")
|
|
||||||
{
|
{
|
||||||
Py_Initialize();
|
try
|
||||||
PyObject *sysPath = PySys_GetObject((char *)"path");
|
{
|
||||||
PyObject *path = PyUnicode_FromString(this->pathToScripts.c_str());
|
pybind11::module_ metricsModule = pybind11::module_::import("plots");
|
||||||
PyList_Insert(sysPath, 0, path);
|
auto result = metricsModule.attr("generatePlots")(pathToTrace).cast<std::string>();
|
||||||
Py_DECREF(path);
|
return result;
|
||||||
|
}
|
||||||
qDebug() << "Metric:" << metricModuleName.c_str() << metricFunctionName.c_str();
|
catch (std::exception const &err)
|
||||||
qDebug() << "Plot:" << plotsModuleName.c_str() << plotsFunctionName.c_str();
|
{
|
||||||
qDebug() << "VcdExport:" << vcdExportModuleName.c_str() << vcdExportFunctionName.c_str();
|
std::cout << err.what() << std::endl;
|
||||||
qDebug() << "Script: " << pathToScripts.c_str();
|
|
||||||
|
|
||||||
pCalculateMetricsFunction = loadFunctionFromModule(metricModuleName,
|
|
||||||
metricFunctionName);
|
|
||||||
pGenPlotsFunction = loadFunctionFromModule(plotsModuleName, plotsFunctionName);
|
|
||||||
pGetMetricsFunction = loadFunctionFromModule(metricModuleName,
|
|
||||||
getMetricFunctionName);
|
|
||||||
|
|
||||||
pVcdExportDependenciesFunction = loadFunctionFromModule(checkDependenciesModuleName, vcdExportDependenciesFunctionName);
|
|
||||||
|
|
||||||
if (vcdExportDependenciesAvailable())
|
|
||||||
pVcdExportFunction = loadFunctionFromModule(vcdExportModuleName, vcdExportFunctionName);
|
|
||||||
else
|
|
||||||
std::cerr << "Warning: Python module pyvcd or tqdm not installed! Exporting as VCD not possible." << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//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(std::string moduleName, std::string functionName)
|
|
||||||
{
|
|
||||||
PyObject *pModuleName = PyUnicode_FromString(moduleName.c_str());
|
|
||||||
PyObject *pModule = PyImport_Import(pModuleName);
|
|
||||||
|
|
||||||
if (!pModule) {
|
|
||||||
throw std::runtime_error(std::string("Could not load module " + moduleName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PyObject *pFunction = PyObject_GetAttrString(pModule, functionName.c_str());
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
if (!pFunction || !PyCallable_Check(pFunction)) {
|
std::vector<std::string> PythonCaller::availableMetrics(std::string_view pathToTrace)
|
||||||
throw std::runtime_error(
|
{
|
||||||
std::string("Could not load test function " + functionName + "in module " + moduleName));
|
try
|
||||||
|
{
|
||||||
|
pybind11::module_ metricsModule = pybind11::module_::import("metrics");
|
||||||
|
pybind11::list result = metricsModule.attr("getMetrics")(pathToTrace);
|
||||||
|
return result.cast<std::vector<std::string>>();
|
||||||
|
}
|
||||||
|
catch (std::exception const &err)
|
||||||
|
{
|
||||||
|
std::cout << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_DECREF(pModuleName);
|
return {};
|
||||||
Py_DECREF(pModule);
|
|
||||||
return pFunction;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PythonCaller::~PythonCaller()
|
TraceCalculatedMetrics PythonCaller::evaluateMetrics(std::string_view pathToTrace, std::vector<long> selectedMetrics)
|
||||||
{
|
{
|
||||||
Py_DECREF(pCalculateMetricsFunction);
|
TraceCalculatedMetrics metrics(pathToTrace.data());
|
||||||
Py_DECREF(pGenPlotsFunction);
|
|
||||||
Py_DECREF(pGetMetricsFunction);
|
|
||||||
|
|
||||||
if (pVcdExportFunction)
|
try
|
||||||
Py_DECREF(pVcdExportFunction);
|
{
|
||||||
|
pybind11::module_ metricsModule = pybind11::module_::import("metrics");
|
||||||
|
pybind11::list result = metricsModule.attr("calculateMetrics")(pathToTrace, selectedMetrics);
|
||||||
|
auto metricList = result.cast<std::vector<pybind11::tuple>>();
|
||||||
|
|
||||||
Py_DECREF(pVcdExportDependenciesFunction);
|
for (auto metricPair : metricList)
|
||||||
Py_Finalize();
|
{
|
||||||
}
|
std::string name = metricPair[0].cast<std::string>();
|
||||||
|
double value = metricPair[1].cast<double>();
|
||||||
PyObject *PythonCaller::callMetricsFunction(PyObject *function, QString argument, std::vector<long> list)
|
metrics.addCalculatedMetric({name, value});
|
||||||
{
|
}
|
||||||
assert(PyCallable_Check(function));
|
|
||||||
|
|
||||||
PyObject *pArgs = PyTuple_New(2);
|
|
||||||
PyObject *pArgumentString = PyUnicode_FromString(
|
|
||||||
argument.toStdString().c_str());
|
|
||||||
PyObject *pArgumentList = PyList_New(list.size());
|
|
||||||
for (size_t i = 0; i < list.size(); i++) {
|
|
||||||
PyList_SetItem(pArgumentList, i, PyBool_FromLong(list[i]));
|
|
||||||
}
|
}
|
||||||
PyTuple_SetItem(pArgs, 0, pArgumentString);
|
catch (std::exception const &err)
|
||||||
PyTuple_SetItem(pArgs, 1, pArgumentList);
|
{
|
||||||
PyObject *pResult = PyObject_CallObject(function, pArgs);
|
std::cout << err.what() << std::endl;
|
||||||
Py_DECREF(pArgs);
|
|
||||||
|
|
||||||
if (!pResult) {
|
|
||||||
PyErr_Print();
|
|
||||||
throw std::runtime_error(
|
|
||||||
std::string("Error in calling " + metricFunctionName + " in module " + metricModuleName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pResult;
|
return metrics;
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns a new reference to result of function call
|
std::string PythonCaller::dumpVcd(std::string_view pathToTrace)
|
||||||
PyObject *PythonCaller::callFunctionWithStringArgument(PyObject *function,
|
|
||||||
QString argument)
|
|
||||||
{
|
{
|
||||||
assert(PyCallable_Check(function));
|
try
|
||||||
|
{
|
||||||
PyObject *pArgs = PyTuple_New(1);
|
pybind11::module_ vcdModule = pybind11::module_::import("vcdExport");
|
||||||
PyObject *pArgument = PyUnicode_FromString(argument.toStdString().c_str());
|
pybind11::str result = vcdModule.attr("dumpVcd")(pathToTrace);
|
||||||
PyTuple_SetItem(pArgs, 0, pArgument);
|
return result.cast<std::string>();
|
||||||
PyObject *pResult = PyObject_CallObject(function, pArgs);
|
}
|
||||||
Py_DECREF(pArgument);
|
catch (std::exception const &err)
|
||||||
|
{
|
||||||
if (!pResult) {
|
std::cout << err.what() << std::endl;
|
||||||
PyErr_Print();
|
|
||||||
throw std::runtime_error(std::string("Error in calling function with string argument"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return pResult;
|
return {};
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *PythonCaller::callFunctionWithoutArguments(PyObject *function)
|
|
||||||
{
|
|
||||||
assert(PyCallable_Check(function));
|
|
||||||
PyObject *pResult = PyObject_CallObject(function, NULL);
|
|
||||||
|
|
||||||
if (!pResult) {
|
|
||||||
PyErr_Print();
|
|
||||||
throw std::runtime_error(std::string("Error in calling python function"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return pResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
TraceCalculatedMetrics PythonCaller::calculateMetricsOnTrace(QString pathToTrace, std::vector<long> list)
|
|
||||||
{
|
|
||||||
TraceCalculatedMetrics result(QFileInfo(pathToTrace).baseName());
|
|
||||||
PyObject *pResult = callMetricsFunction(pCalculateMetricsFunction, pathToTrace,
|
|
||||||
list);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> PythonCaller::getMetrics(QString pathToTrace)
|
|
||||||
{
|
|
||||||
std::vector<std::string> result;
|
|
||||||
PyObject *pResult = callFunctionWithStringArgument(pGetMetricsFunction,
|
|
||||||
pathToTrace);
|
|
||||||
|
|
||||||
for (Py_ssize_t i = 0; i < PyList_Size(pResult); ++i) {
|
|
||||||
PyObject *metric = PyList_GetItem(pResult, i);
|
|
||||||
QString metricName(PyUnicode_AsUTF8(metric));
|
|
||||||
result.push_back(metricName.toStdString().c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_DECREF(pResult);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PythonCaller::generatePlotsOnTrace(QString pathToTrace)
|
|
||||||
{
|
|
||||||
assert(PyCallable_Check(pGenPlotsFunction));
|
|
||||||
|
|
||||||
PyObject *pResult = callFunctionWithStringArgument(pGenPlotsFunction,
|
|
||||||
pathToTrace);
|
|
||||||
QString outputFiles (PyUnicode_AsUTF8(pResult));
|
|
||||||
Py_DECREF(pResult);
|
|
||||||
return outputFiles;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
QString PythonCaller::exportAsVcd(QString pathToTrace)
|
|
||||||
{
|
|
||||||
if (!pVcdExportFunction)
|
|
||||||
return QString();
|
|
||||||
|
|
||||||
PyObject *pResult = callFunctionWithStringArgument(pVcdExportFunction, pathToTrace);
|
|
||||||
|
|
||||||
QString dump(PyUnicode_AsUTF8(pResult));
|
|
||||||
Py_DECREF(pResult);
|
|
||||||
return dump;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PythonCaller::vcdExportDependenciesAvailable()
|
|
||||||
{
|
|
||||||
PyObject *result = callFunctionWithoutArguments(pVcdExportDependenciesFunction);
|
|
||||||
bool available = PyObject_IsTrue(result);
|
|
||||||
Py_DECREF(result);
|
|
||||||
|
|
||||||
return available;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,47 +45,16 @@
|
|||||||
#undef slots
|
#undef slots
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <Python.h>
|
|
||||||
#include <QString>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include "businessObjects/tracecalculatedmetrics.h"
|
#include "businessObjects/tracecalculatedmetrics.h"
|
||||||
|
|
||||||
class PythonCaller
|
class PythonCaller
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PythonCaller();
|
static std::vector<std::string> availableMetrics(std::string_view pathToTrace);
|
||||||
~PythonCaller();
|
static TraceCalculatedMetrics evaluateMetrics(std::string_view pathToTrace, std::vector<long> selectedMetrics);
|
||||||
|
static std::string generatePlots(std::string_view pathToTrace);
|
||||||
TraceCalculatedMetrics calculateMetricsOnTrace(QString pathToTrace,
|
static std::string dumpVcd(std::string_view pathToTrace);
|
||||||
std::vector<long> list);
|
|
||||||
std::vector<std::string> getMetrics(QString pathToTrace);
|
|
||||||
QString generatePlotsOnTrace(QString pathToTrace);
|
|
||||||
|
|
||||||
bool vcdExportDependenciesAvailable();
|
|
||||||
QString exportAsVcd(QString pathToTrace);
|
|
||||||
|
|
||||||
private:
|
|
||||||
PyObject *pCalculateMetricsFunction, *pGetMetricsFunction;
|
|
||||||
PyObject *pGenPlotsFunction;
|
|
||||||
PyObject *pVcdExportFunction = nullptr;
|
|
||||||
PyObject *pVcdExportDependenciesFunction;
|
|
||||||
PyObject *loadFunctionFromModule(std::string moduleName,
|
|
||||||
std::string functionName);
|
|
||||||
std::string metricModuleName, metricFunctionName, getMetricFunctionName, pathToScripts;
|
|
||||||
std::string plotsModuleName;
|
|
||||||
std::string plotsFunctionName;
|
|
||||||
|
|
||||||
std::string checkDependenciesModuleName;
|
|
||||||
|
|
||||||
std::string vcdExportModuleName;
|
|
||||||
std::string vcdExportFunctionName;
|
|
||||||
std::string vcdExportDependenciesFunctionName;
|
|
||||||
|
|
||||||
PyObject *callFunctionWithStringArgument(PyObject *function, QString argument);
|
|
||||||
PyObject *callFunctionWithoutArguments(PyObject *function);
|
|
||||||
PyObject *callMetricsFunction(PyObject *function, QString argument,
|
|
||||||
std::vector<long> list);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PYTHONCALLER_H
|
#endif // PYTHONCALLER_H
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
result.append("Trace");
|
result.append("Trace");
|
||||||
for (CalculatedMetric calculatedMetric : calculatedMetrics) {
|
for (CalculatedMetric calculatedMetric : calculatedMetrics) {
|
||||||
result.append(",");
|
result.append(",");
|
||||||
result.append(calculatedMetric.getName());
|
result.append(calculatedMetric.name.c_str());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -76,7 +76,7 @@ public:
|
|||||||
result.append(traceName);
|
result.append(traceName);
|
||||||
for (CalculatedMetric calculatedMetric : calculatedMetrics) {
|
for (CalculatedMetric calculatedMetric : calculatedMetrics) {
|
||||||
result.append(",");
|
result.append(",");
|
||||||
result.append(QString::number(calculatedMetric.getValue()));
|
result.append(QString::number(calculatedMetric.value));
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,11 +51,9 @@
|
|||||||
#include "evaluationtool.h"
|
#include "evaluationtool.h"
|
||||||
#include "ui_evaluationtool.h"
|
#include "ui_evaluationtool.h"
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
EvaluationTool::EvaluationTool(PythonCaller &pythonCaller, QWidget *parent) :
|
EvaluationTool::EvaluationTool(PythonCaller &pythonCaller, QWidget *parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::EvaluationTool), resourcesRelPath("/../../dram/resources/scripts"""), pythonCaller(pythonCaller)
|
ui(new Ui::EvaluationTool), pythonCaller(pythonCaller)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
traceFilesModel = new QStandardItemModel(this);
|
traceFilesModel = new QStandardItemModel(this);
|
||||||
@@ -85,16 +83,15 @@ void EvaluationTool::showAndEvaluateMetrics(QList<QString> paths)
|
|||||||
show();
|
show();
|
||||||
ui->toolBox->setCurrentIndex(1);
|
ui->toolBox->setCurrentIndex(1);
|
||||||
selectMetrics->setMetrics(getMetrics());
|
selectMetrics->setMetrics(getMetrics());
|
||||||
cout << "done" << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<string> EvaluationTool::getMetrics()
|
std::vector<std::string> EvaluationTool::getMetrics()
|
||||||
{
|
{
|
||||||
vector<string> metrics;
|
std::vector<std::string> metrics;
|
||||||
for (int row = 0; row < traceFilesModel->rowCount(); ++row) {
|
for (int row = 0; row < traceFilesModel->rowCount(); ++row) {
|
||||||
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
||||||
vector<string> result = pythonCaller.getMetrics(item->getPath());
|
std::vector<std::string> result = PythonCaller::availableMetrics(item->getPath().toStdString());
|
||||||
if (result.size() > metrics.size())
|
if (result.size() > metrics.size()) // TODO use std::set
|
||||||
metrics = result;
|
metrics = result;
|
||||||
}
|
}
|
||||||
return metrics;
|
return metrics;
|
||||||
@@ -127,22 +124,21 @@ void EvaluationTool::on_btn_calculateMetrics_clicked()
|
|||||||
|
|
||||||
void EvaluationTool::getSelectedMetrics()
|
void EvaluationTool::getSelectedMetrics()
|
||||||
{
|
{
|
||||||
vector<long> selectedMetrics;
|
std::vector<long> selectedMetrics;
|
||||||
for (QCheckBox *metric : selectMetrics->metrics) {
|
for (QCheckBox *metric : selectMetrics->metrics) {
|
||||||
selectedMetrics.push_back(metric->isChecked());
|
selectedMetrics.push_back(metric->isChecked());
|
||||||
}
|
}
|
||||||
calculateMetrics(selectedMetrics);
|
calculateMetrics(selectedMetrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvaluationTool::calculateMetrics(vector<long> selectedMetrics)
|
void EvaluationTool::calculateMetrics(std::vector<long> selectedMetrics)
|
||||||
{
|
{
|
||||||
ui->traceMetricTreeWidget->clear();
|
ui->traceMetricTreeWidget->clear();
|
||||||
for (int row = 0; row < traceFilesModel->rowCount(); ++row) {
|
for (int row = 0; row < traceFilesModel->rowCount(); ++row) {
|
||||||
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
||||||
if (item->checkState() == Qt::Checked)
|
if (item->checkState() == Qt::Checked)
|
||||||
{
|
{
|
||||||
TraceCalculatedMetrics result = pythonCaller.calculateMetricsOnTrace(
|
TraceCalculatedMetrics result = pythonCaller.evaluateMetrics(item->getPath().toStdString(), selectedMetrics);
|
||||||
item->getPath(), selectedMetrics);
|
|
||||||
calculatedMetrics.push_back(result);
|
calculatedMetrics.push_back(result);
|
||||||
ui->traceMetricTreeWidget->addTraceMetricResults(result);
|
ui->traceMetricTreeWidget->addTraceMetricResults(result);
|
||||||
}
|
}
|
||||||
@@ -194,9 +190,9 @@ void EvaluationTool::genPlots()
|
|||||||
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
TraceFileItem *item = static_cast<TraceFileItem *>(traceFilesModel->item(row));
|
||||||
if (item->checkState() == Qt::Checked)
|
if (item->checkState() == Qt::Checked)
|
||||||
{
|
{
|
||||||
ui->traceMetricTreeWidget->addTracePlotResults(QFileInfo(
|
ui->traceMetricTreeWidget->addTracePlotResults(
|
||||||
item->getPath()).baseName(),
|
QFileInfo(item->getPath()).baseName(),
|
||||||
pythonCaller.generatePlotsOnTrace(item->getPath()));
|
PythonCaller::generatePlots(item->getPath().toStdString()).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui->traceMetricTreeWidget->expandAll();
|
ui->traceMetricTreeWidget->expandAll();
|
||||||
|
|||||||
@@ -84,7 +84,6 @@ private:
|
|||||||
Ui::EvaluationTool *ui;
|
Ui::EvaluationTool *ui;
|
||||||
QStandardItemModel *traceFilesModel;
|
QStandardItemModel *traceFilesModel;
|
||||||
std::vector<TraceCalculatedMetrics> calculatedMetrics;
|
std::vector<TraceCalculatedMetrics> calculatedMetrics;
|
||||||
QString resourcesRelPath;
|
|
||||||
SelectMetrics *selectMetrics;
|
SelectMetrics *selectMetrics;
|
||||||
|
|
||||||
PythonCaller &pythonCaller;
|
PythonCaller &pythonCaller;
|
||||||
|
|||||||
@@ -42,7 +42,9 @@
|
|||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <pybind11/embed.h>
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@@ -54,6 +56,16 @@ int main(int argc, char *argv[])
|
|||||||
a.setApplicationName(QStringLiteral("TraceAnalyzer"));
|
a.setApplicationName(QStringLiteral("TraceAnalyzer"));
|
||||||
a.setApplicationDisplayName(QStringLiteral("Trace Analyzer"));
|
a.setApplicationDisplayName(QStringLiteral("Trace Analyzer"));
|
||||||
|
|
||||||
|
std::filesystem::path traceAnalyzerDir = DRAMSYS_TRACEANALYZER_DIR;
|
||||||
|
std::filesystem::path modulesDir = traceAnalyzerDir / "scripts";
|
||||||
|
|
||||||
|
pybind11::scoped_interpreter guard;
|
||||||
|
|
||||||
|
// Add scripts directory to local module search path
|
||||||
|
pybind11::module_ sys = pybind11::module_::import("sys");
|
||||||
|
pybind11::list path = sys.attr("path");
|
||||||
|
path.append(modulesDir.c_str());
|
||||||
|
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
QSet<QString> arguments;
|
QSet<QString> arguments;
|
||||||
for (int i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ void TraceMetricTreeWidget::addTraceMetricResults(const TraceCalculatedMetrics
|
|||||||
new QTreeWidgetItem(top, {QString("Number of threads: 1")});
|
new QTreeWidgetItem(top, {QString("Number of threads: 1")});
|
||||||
} else {
|
} else {
|
||||||
for (CalculatedMetric calculatedMetric : result.getCalculatedMetrics()) {
|
for (CalculatedMetric calculatedMetric : result.getCalculatedMetrics()) {
|
||||||
new QTreeWidgetItem(top, {calculatedMetric.getName() + QString(": ") + QString::number(calculatedMetric.getValue(), 'f')});
|
new QTreeWidgetItem(top, {calculatedMetric.name.c_str() + QString(": ") + QString::number(calculatedMetric.value, 'f')});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
4
extensions/apps/traceAnalyzer/scripts/requirements.txt
Normal file
4
extensions/apps/traceAnalyzer/scripts/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
matplotlib
|
||||||
|
numpy
|
||||||
|
pyvcd
|
||||||
|
tqdm
|
||||||
@@ -127,13 +127,12 @@ void TraceAnalyzer::on_menuFile_aboutToShow()
|
|||||||
ui->actionQuit->setEnabled(true);
|
ui->actionQuit->setEnabled(true);
|
||||||
|
|
||||||
bool tabsOpen = ui->traceFileTabs->count() > 0;
|
bool tabsOpen = ui->traceFileTabs->count() > 0;
|
||||||
bool exportAsVcdAvailable = pythonCaller.vcdExportDependenciesAvailable();
|
|
||||||
|
|
||||||
ui->actionSave->setEnabled(tabsOpen);
|
ui->actionSave->setEnabled(tabsOpen);
|
||||||
ui->actionSave_all->setEnabled(tabsOpen);
|
ui->actionSave_all->setEnabled(tabsOpen);
|
||||||
ui->actionReload->setEnabled(tabsOpen);
|
ui->actionReload->setEnabled(tabsOpen);
|
||||||
ui->actionReload_all->setEnabled(tabsOpen);
|
ui->actionReload_all->setEnabled(tabsOpen);
|
||||||
ui->actionExportAsVCD->setEnabled(tabsOpen && exportAsVcdAvailable);
|
ui->actionExportAsVCD->setEnabled(tabsOpen);
|
||||||
ui->actionTest->setEnabled(tabsOpen);
|
ui->actionTest->setEnabled(tabsOpen);
|
||||||
ui->actionMetrics->setEnabled(tabsOpen);
|
ui->actionMetrics->setEnabled(tabsOpen);
|
||||||
ui->actionClose->setEnabled(tabsOpen);
|
ui->actionClose->setEnabled(tabsOpen);
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
#include "businessObjects/commentmodel.h"
|
#include "businessObjects/commentmodel.h"
|
||||||
#include "businessObjects/configmodels.h"
|
#include "businessObjects/configmodels.h"
|
||||||
#include "businessObjects/dramTimeDependencies/phasedependenciestracker.h"
|
#include "businessObjects/dramTimeDependencies/phasedependenciestracker.h"
|
||||||
#include "businessObjects/pythoncaller.h"
|
|
||||||
#include "businessObjects/traceplotlinemodel.h"
|
#include "businessObjects/traceplotlinemodel.h"
|
||||||
#include "businessObjects/tracetime.h"
|
#include "businessObjects/tracetime.h"
|
||||||
#include "queryeditor.h"
|
#include "queryeditor.h"
|
||||||
@@ -68,6 +67,9 @@
|
|||||||
#include <qwt_scale_draw.h>
|
#include <qwt_scale_draw.h>
|
||||||
#include <qwt_scale_widget.h>
|
#include <qwt_scale_widget.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
TraceFileTab::TraceFileTab(std::string_view traceFilePath, PythonCaller &pythonCaller, QWidget *parent)
|
TraceFileTab::TraceFileTab(std::string_view traceFilePath, PythonCaller &pythonCaller, QWidget *parent)
|
||||||
: QWidget(parent), ui(new Ui::TraceFileTab), commentModel(new CommentModel(this)),
|
: QWidget(parent), ui(new Ui::TraceFileTab), commentModel(new CommentModel(this)),
|
||||||
navigator(new TraceNavigator(traceFilePath.data(), commentModel, this)),
|
navigator(new TraceNavigator(traceFilePath.data(), commentModel, this)),
|
||||||
@@ -117,23 +119,14 @@ void TraceFileTab::commitChangesToDB()
|
|||||||
|
|
||||||
void TraceFileTab::exportAsVCD()
|
void TraceFileTab::exportAsVCD()
|
||||||
{
|
{
|
||||||
QString filename = QFileDialog::getSaveFileName(this, "Export to VCD", "",
|
std::string filename = QFileDialog::getSaveFileName(this, "Export to VCD", "", "VCD files (*.vcd)").toStdString();
|
||||||
"VCD files (*.vcd)");
|
|
||||||
auto dumpVcd = [=]() {
|
|
||||||
QString dump = pythonCaller.exportAsVcd(traceFilePath.data());
|
|
||||||
|
|
||||||
QFile file(filename);
|
auto dump = PythonCaller::dumpVcd(traceFilePath);
|
||||||
file.open(QIODevice::WriteOnly | QIODevice::Text);
|
|
||||||
QTextStream out(&file);
|
std::ofstream file(filename);
|
||||||
out << dump;
|
file << dump;
|
||||||
file.close();
|
|
||||||
|
|
||||||
Q_EMIT statusChanged(QString("VCD export finished."));
|
Q_EMIT statusChanged(QString("VCD export finished."));
|
||||||
};
|
|
||||||
|
|
||||||
if (filename != "") {
|
|
||||||
QtConcurrent::run(dumpVcd);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TraceFileTab::setUpTraceSelector()
|
void TraceFileTab::setUpTraceSelector()
|
||||||
|
|||||||
Reference in New Issue
Block a user