Merge branch 'opensource-traceanalyzer' into 'develop'

Move Trace Analyzer to open source tree

See merge request ems/astdm/modeling.dram/dram.sys.5!73
This commit is contained in:
Lukas Steiner
2024-07-18 09:36:34 +00:00
98 changed files with 706 additions and 1430 deletions

View File

@@ -91,12 +91,12 @@ set(DRAMSYS_EXTENSIONS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/extensions")
### Build options ###
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
option(DRAMSYS_VERBOSE_CMAKE_OUTPUT "Show detailed CMake output" OFF)
option(DRAMSYS_BUILD_TESTS "Build DRAMSys unit tests" OFF)
option(DRAMSYS_BUILD_BENCHMARKS "Build DRAMSys benchmarks" OFF)
option(DRAMSYS_VERBOSE_CMAKE_OUTPUT "Show detailed CMake output" OFF)
option(DRAMSYS_BUILD_CLI "Build DRAMSys Command Line Tool" ON)
option(DRAMSYS_BUILD_TRACE_ANALYZER "Build DRAMSys Trace Analyzer" OFF)
option(DRAMSYS_WITH_DRAMPOWER "Build with DRAMPower support enabled." OFF)
option(DRAMSYS_ENABLE_EXTENSIONS "Enable proprietary DRAMSys extensions." OFF)
option(DRAMSYS_USE_EXTERNAL_SYSTEMC "Use an external SystemC installation." OFF)
###############################################
@@ -156,10 +156,14 @@ set(DISABLE_COPYRIGHT_MESSAGE True)
# Allow populating of a user-set SystemC package
if (NOT TARGET SystemC::systemc)
FetchContent_MakeAvailable(systemc)
# Set include directories to SYSTEM to suppress warnings
set_target_properties(systemc PROPERTIES SYSTEM TRUE)
else()
# Set include directories to SYSTEM to suppress warnings
set_target_properties(SystemC::systemc PROPERTIES SYSTEM TRUE)
endif()
# Set include directories to SYSTEM to suppress warnings
set_target_properties(systemc PROPERTIES SYSTEM TRUE)
### DRAMPower ###
if (DRAMSYS_WITH_DRAMPOWER)
@@ -184,10 +188,12 @@ if(DRAMSYS_BUILD_CLI)
add_subdirectory(src/simulator)
endif()
if(DRAMSYS_ENABLE_EXTENSIONS)
dramsys_enable_extensions()
if(DRAMSYS_BUILD_TRACE_ANALYZER)
add_subdirectory(src/traceAnalyzer)
endif()
dramsys_enable_extensions()
###############################################
### Test Directory ###
###############################################
@@ -202,6 +208,6 @@ endif()
### Benchmark Directory ###
###############################################
if(DRAMSYS_BUILD_BENCHMARKS)
if(DRAMSYS_BUILD_BENCHMARKS)
add_subdirectory(benches)
endif()

View File

@@ -22,8 +22,8 @@
"inherits": "cmake-pedantic",
"cacheVariables": {
"DRAMSYS_BUILD_TESTS": "ON",
"DRAMSYS_ENABLE_EXTENSIONS": "ON",
"DRAMSYS_WITH_DRAMPOWER": "ON"
"DRAMSYS_WITH_DRAMPOWER": "ON",
"DRAMSYS_BUILD_TRACE_ANALYZER": "ON"
}
},
{

View File

@@ -18,6 +18,7 @@ If you decide to use DRAMSys in your research please cite the paper [2] or [3].
## Included Features
- **Standalone** simulator with trace players and traffic generators or **TLM-2.0-compliant library**
- **Trace Analyzer** for visual and metric-based result analysis
- Coupling to **gem5** supported
- Cycle-accurate **DDR3/4**, **LPDDR4**, **Wide I/O 1/2**, **GDDR5/5X/6** and **HBM1/2** modelling
- Bit-granular address mapping with optional XOR connections [7]
@@ -31,7 +32,7 @@ If you decide to use DRAMSys in your research please cite the paper [2] or [3].
## Additional Features
- Cycle-accurate **DDR5**, **LPDDR5** and **HBM3** modelling
- **Trace Analyzer** for visual and metric-based result analysis
- Extended analysis features for the **Trace Analyzer**
- **Free academic** or **commercial** licenses available (please contact [DRAMSys@iese.fraunhofer.de](mailto:DRAMSys@iese.fraunhofer.de) for more information)
## Video
@@ -48,7 +49,15 @@ All requests, responses and DRAM commands can be recorded in an SQLite trace dat
The Trace Analyzer's main window is shown below.
If you are interested in the Trace Analyzer, if you need support with the setup of DRAMSys in a virtual platform of your company, or if you require custom modifications of the simulator please contact [DRAMSys@iese.fraunhofer.de](mailto:DRAMSys@iese.fraunhofer.de).
A basic version of Trace Analyzer is included in the open source release of DRAMSys.
However, the full version of the Trace Analyzer includes many additional analysis features:
- Detailed transaction-level latency analysis
- Power, bandwidth, and buffer utilization analysis over simulation time intervals
- Timing dependency analysis at the DRAM command level
- Calculation of numerous predefined and user-defined metrics
- VCD export of generated trace
If you are interested in the full version of Trace Analyzer, if you need support with the setup of DRAMSys in a virtual platform of your company, or if you require custom modifications of the simulator please contact [DRAMSys@iese.fraunhofer.de](mailto:DRAMSys@iese.fraunhofer.de).
![Trace Analyzer Main Window](docs/images/traceanalyzer.png)
@@ -58,7 +67,10 @@ To use DRAMSys, first clone the repository.
### Dependencies
DRAMSys requires a **C++17** compiler. The build process is based on **CMake** (minimum version **3.24**). Furthermore, the simulator is based on **SystemC**. SystemC is included with FetchContent and will be build automatically with the project. If you want to use a preinstalled SystemC version, export the environment variable `SYSTEMC_HOME` (SystemC installation directory) and set the CMake option `DRAMSYS_USE_EXTERNAL_SYSTEMC`. Also make sure that the SystemC library was built with the same C++ version.
DRAMSys requires a **C++17** compiler. The build process is based on **CMake** (minimum version **3.24**). Furthermore, the simulator is based on **SystemC**. SystemC is included with FetchContent and will be build automatically with the project. If you want to use a preinstalled SystemC version, export the environment variable `SYSTEMC_HOME` (SystemC installation directory) and enable the `DRAMSYS_USE_EXTERNAL_SYSTEMC` CMake option. Also make sure that the SystemC library was built with the same C++ version.
If you choose to enable the compilation of the Trace Analyzer, a system installation of development packages for Qt5, Qwt and Python is required.
For example, on Ubuntu, these dependencies can be satisfied by installing the `qtbase5-dev`, `libqwt-qt5-dev` and `python3-dev` packages.
### Building DRAMSys
@@ -77,7 +89,9 @@ $ cmake -B build -D DRAMSYS_WITH_DRAMPOWER=Y
If you plan to integrate DRAMSys into your own SystemC TLM-2.0 project you can build only the DRAMSys library by disabling the CMake option `DRAMSYS_BUILD_CLI`.
In order to include any proprietary extensions such as the Trace Analyzer, enable the CMake option `DRAMSYS_ENABLE_EXTENSIONS`.
To include the Trace Analyzer in the build process, enable the CMake option `DRAMSYS_BUILD_TRACE_ANALYZER`.
In order to include any proprietary extensions such as the extended features of Trace Analyzer, enable the CMake option `DRAMSYS_ENABLE_EXTENSIONS`.
To build DRAMSys on Windows 10 we recommend to use the **Windows Subsystem for Linux (WSL)**.

View File

@@ -6,12 +6,11 @@
##############################################
##############################################
message(STATUS " Apps:")
##############################################
### TraceAnalyzer ###
##############################################
option(DRAMSYS_EXTENSION_TRACE_ANALYZER_ENABLE "Enable DRAMSys Trace Analyzer" ON)
if(DRAMSYS_EXTENSION_TRACE_ANALYZER_ENABLE)
message(STATUS " * Trace Analyzer")
IF(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/traceAnalyzer")
add_subdirectory(traceAnalyzer)
endif()
ENDIF()

View File

@@ -1,8 +0,0 @@
[Dolphin]
Timestamp=2022,2,16,16,1,1.259
Version=4
ViewMode=1
VisibleRoles=Details_text,Details_type,Details_size,Details_modificationtime,CustomizedDetails
[Settings]
HiddenFilesShown=true

View File

@@ -1,102 +1,14 @@
# Copyright (c) 2020, RPTU Kaiserslautern-Landau
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors:
# Matthias Jung
# Lukas Steiner
# Derek Christ
# Iron Prando da Silva
option(DRAMSYS_EXTENSION_TRACE_ANALYZER_ENABLE "Enable Trace Analyzer extension" ON)
########################################
### TraceAnalyzer ###
########################################
if(DRAMSYS_EXTENSION_TRACE_ANALYZER_ENABLE AND TARGET TraceAnalyzer)
message(STATUS " * Trace Analyzer")
project(TraceAnalyzer)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
target_sources(TraceAnalyzer PRIVATE ${SOURCE_FILES} ${HEADER_FILES})
target_include_directories(TraceAnalyzer PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_definitions(TraceAnalyzer PRIVATE EXTENSION_ENABLED)
# Add Python3 Dependency:
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:
find_library(QWT_LIBRARY NAMES "qwt" "qwt-qt5" PATHS
"$ENV{QWT_HOME}/lib"
"/opt/homebrew/opt/qwt-qt5/lib"
)
find_path(QWT_INCLUDE_DIRS NAMES "qwt_plot.h" PATHS
"$ENV{QWT_HOME}/include"
"/usr/include/qwt-qt5"
"/usr/include/qwt"
"/opt/homebrew/opt/qwt-qt5/include"
"/opt/homebrew/opt/qwt-qt5/lib/qwt.framework/Headers"
)
# Add QT Library:
if (APPLE)
set(Qt5_DIR "/opt/homebrew/opt/qt@5/lib/cmake/Qt5")
endif(APPLE)
find_package(Qt5 COMPONENTS Core Gui Widgets Sql REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(TraceAnalyzer ${SOURCE_FILES} ${HEADER_FILES})
target_include_directories(TraceAnalyzer
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
PRIVATE ${QWT_INCLUDE_DIRS}
)
target_link_libraries(TraceAnalyzer
PRIVATE pybind11::embed
PRIVATE ${QWT_LIBRARY}
PRIVATE Qt5::Widgets
PRIVATE Qt5::Sql
PRIVATE DRAMSys::util
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()
endif()

View File

@@ -35,7 +35,7 @@
#pragma once
#include "../data/tracedb.h"
#include "data/tracedb.h"
#include "phases/dependencyinfos.h"
#include <QAbstractTableModel>

View File

@@ -34,7 +34,7 @@
*/
#include "phasedependency.h"
#include "phase.h"
#include "businessObjects/phases/phase.h"
#include <iostream>
PhaseDependency::PhaseDependency(DependencyType type,

View File

@@ -1,400 +0,0 @@
/*
* Copyright (c) 2021, RPTU Kaiserslautern-Landau
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Derek Christ
*/
#include "simulationdialog.h"
#include "DRAMSys/config/TraceSetup.h"
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QRegularExpression>
#include <optional>
SimulationDialog::SimulationDialog(QWidget* parent) : QWidget(parent), ui(new Ui::SimulationDialog)
{
ui->setupUi(this);
showStopButton(false);
// Try to find path to DRAMSys
{
QFileInfo fileInfo;
fileInfo.setFile("../simulator/DRAMSys");
if (fileInfo.isFile())
ui->dramSysPath->setText(fileInfo.absoluteFilePath());
fileInfo.setFile("../simulator/DRAMSys.exe");
if (fileInfo.isFile())
ui->dramSysPath->setText(fileInfo.absoluteFilePath());
fileInfo.setFile("simulator/DRAMSys");
if (fileInfo.isFile())
ui->dramSysPath->setText(fileInfo.absoluteFilePath());
fileInfo.setFile("simulator/DRAMSys.exe");
if (fileInfo.isFile())
ui->dramSysPath->setText(fileInfo.absoluteFilePath());
}
ui->outputDirLineEdit->setText(QDir::currentPath());
}
void SimulationDialog::on_browseDramSysButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(
this, ui->browseDramSysButton->text(), {}, "DRAMSys executable (*)");
ui->dramSysPath->setText(fileName);
}
void SimulationDialog::on_browseConfigButton_clicked()
{
QString fileName = QFileDialog::getOpenFileName(
this, ui->browseConfigButton->text(), {}, "Configuration file (*.json)");
ui->jsonPath->setText(fileName);
loadConfigurationFromPath();
}
void SimulationDialog::on_browseOutputButton_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(this, ui->browseOutputButton->text(), {});
ui->outputDirLineEdit->setText(fileName);
loadConfigurationFromPath();
}
void SimulationDialog::on_browseResourceDirButton_clicked()
{
QString fileName =
QFileDialog::getExistingDirectory(this, ui->browseResourceDirButton->text(), {});
ui->resourceDirLineEdit->setText(fileName);
loadConfigurationFromPath();
}
void SimulationDialog::on_simulateButton_clicked()
{
saveConfiguration(temporaryConfigurationFile);
ui->tabWidget->setCurrentWidget(ui->outputTab);
ui->progressBar->setEnabled(true);
ui->progressBar->setValue(0);
showStopButton(true);
// Spawn the DRAMSys process
simulatorProcess = new QProcess(this);
QObject::connect(simulatorProcess,
&QIODevice::readyRead,
this,
[=]
{
QByteArray msg = simulatorProcess->read(4096);
msg = msg.trimmed();
processMessage(msg.toStdString());
});
QObject::connect(simulatorProcess,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this,
[=](int exitCode, QProcess::ExitStatus exitStatus)
{
Q_UNUSED(exitStatus)
showStopButton(false);
// Clear all the contents so that the user is not asked
// next time to overwrite the temp file.
temporaryConfigurationFile.resize(0);
if (exitCode == 0)
{
ui->progressBar->setValue(100);
QMessageBox msgBox;
msgBox.setText("Simulation done.");
msgBox.setInformativeText("Do you want to open the results?");
msgBox.setStandardButtons(QMessageBox::Open | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Open);
int ret = msgBox.exec();
if (ret == QMessageBox::Open)
{
auto results = getSimulationResults();
openSimulationResults(results);
}
}
});
QStringList argumentList;
argumentList << temporaryConfigurationFile.fileName();
if (!ui->resourceDirLineEdit->text().isEmpty())
argumentList << ui->resourceDirLineEdit->text();
simulatorProcess->setWorkingDirectory(ui->outputDirLineEdit->text());
simulatorProcess->start(ui->dramSysPath->text(), argumentList);
}
void SimulationDialog::on_reloadButton_clicked()
{
loadConfigurationFromPath();
ui->outputPlainTextEdit->clear();
}
void SimulationDialog::on_saveButton_clicked()
{
QFile file(ui->jsonPath->text());
saveConfiguration(file);
}
void SimulationDialog::on_stopButton_clicked()
{
if (simulatorProcess)
simulatorProcess->terminate();
}
void SimulationDialog::showStopButton(bool val)
{
ui->simulateButton->setVisible(!val);
ui->stopButton->setVisible(val);
}
void SimulationDialog::saveConfiguration(QFile& file)
{
if (!file.open(QIODevice::ReadWrite | QIODevice::Text))
return;
if (file.size() != 0)
{
QMessageBox msgBox;
msgBox.setText("The configuration file will be overwritten.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
if (ret != QMessageBox::Save)
return;
}
// Clear the file
file.resize(0);
QTextStream out(&file);
loadConfigurationFromTextFields();
std::string dump = nlohmann::json(configuration).dump(4);
out << dump.c_str();
}
void SimulationDialog::processMessage(const std::string& msg)
{
// Get percentages
QRegularExpression re("(\\d+(\\.\\d+)?|\\.\\d+) ?%");
QRegularExpressionMatch match = re.match(msg.c_str());
if (match.hasMatch())
{
unsigned int percentage = match.captured(1).toUInt();
ui->progressBar->setValue(percentage);
}
ui->outputPlainTextEdit->appendPlainText(msg.c_str());
}
void SimulationDialog::loadConfigurationFromTextFields()
{
using namespace DRAMSys::Config;
AddressMapping addressMapping;
McConfig mcConfig;
MemSpec memSpec;
SimConfig simConfig;
std::string simulationId;
std::vector<Initiator> traceSetup;
simulationId = ui->simulationIdLineEdit->text().toStdString();
try
{
nlohmann::json::parse(ui->addressMappingTextEdit->toPlainText().toStdString())
.get_to(addressMapping);
nlohmann::json::parse(ui->mcConfigTextEdit->toPlainText().toStdString()).get_to(mcConfig);
nlohmann::json::parse(ui->memSpecTextEdit->toPlainText().toStdString()).get_to(memSpec);
nlohmann::json::parse(ui->simConfigTextEdit->toPlainText().toStdString()).get_to(simConfig);
if (!ui->traceSetupTextEdit->toPlainText().toStdString().empty())
nlohmann::json::parse(ui->traceSetupTextEdit->toPlainText().toStdString())
.get_to(traceSetup);
}
catch (const std::exception& e)
{
qWarning() << "Error while parsing json:" << e.what();
return;
}
configuration = DRAMSys::Config::Configuration{
addressMapping,
mcConfig,
memSpec,
simConfig,
simulationId,
std::make_optional<std::vector<Initiator>>(std::move(traceSetup))};
loadConfiguration();
}
void SimulationDialog::loadConfigurationFromPath()
{
QFileInfo fileInfo(ui->jsonPath->text());
if (!fileInfo.isFile())
return;
try
{
configuration = DRAMSys::Config::from_path(ui->jsonPath->text().toStdString());
}
catch (const std::exception& e)
{
qWarning() << "Error while parsing json:" << e.what();
return;
}
loadConfiguration();
}
void SimulationDialog::loadConfiguration()
{
ui->simulationIdLabel->setEnabled(true);
ui->simulationId->setEnabled(true);
ui->simulationId->setText(configuration.simulationid.c_str());
ui->simulationIdLineEdit->setText(configuration.simulationid.c_str());
loadSimConfig();
loadMcConfig();
loadMemSpec();
loadAddressMapping();
loadTraceSetup();
loadPreview();
}
void SimulationDialog::loadSimConfig()
{
ui->simConfigTextEdit->clear();
std::string dump = nlohmann::json(configuration.simconfig).dump(4);
ui->simConfigTextEdit->setText(dump.c_str());
}
void SimulationDialog::loadMcConfig()
{
ui->mcConfigTextEdit->clear();
std::string dump = nlohmann::json(configuration.mcconfig).dump(4);
ui->mcConfigTextEdit->setText(dump.c_str());
}
void SimulationDialog::loadMemSpec()
{
ui->memSpecTextEdit->clear();
std::string dump = nlohmann::json(configuration.memspec).dump(4);
ui->memSpecTextEdit->setText(dump.c_str());
}
void SimulationDialog::loadAddressMapping()
{
ui->addressMappingTextEdit->clear();
std::string dump = nlohmann::json(configuration.addressmapping).dump(4);
ui->addressMappingTextEdit->setText(dump.c_str());
}
void SimulationDialog::loadTraceSetup()
{
ui->traceSetupTextEdit->clear();
if (const auto& traceSetup = configuration.tracesetup)
{
std::string dump = nlohmann::json(*traceSetup).dump(4);
ui->traceSetupTextEdit->setText(dump.c_str());
}
}
void SimulationDialog::loadPreview()
{
ui->previewTextEdit->clear();
std::string dump = nlohmann::json(configuration).dump(4);
ui->previewTextEdit->setText(dump.c_str());
}
QFileInfoList SimulationDialog::getSimulationResults()
{
QFileInfoList list;
// Get the path where the tracefiles are located
QDir baseDir(ui->outputDirLineEdit->text());
for (const auto& fileInfo : baseDir.entryInfoList())
{
if (fileInfo.baseName().startsWith(configuration.simulationid.c_str()))
{
// Dont open tracefiles that are older than a few seconds
if (fileInfo.metadataChangeTime().secsTo(QDateTime::currentDateTime()) > 30)
continue;
list << fileInfo;
}
}
return list;
}
void SimulationDialog::openSimulationResults(const QFileInfoList& fileInfos)
{
for (const auto& fileInfo : fileInfos)
openFileRequested(fileInfo.absoluteFilePath());
}

View File

@@ -1,394 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SimulationDialog</class>
<widget class="QWidget" name="SimulationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>920</width>
<height>620</height>
</rect>
</property>
<property name="font">
<font/>
</property>
<property name="windowTitle">
<string>Simulation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Simulation</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QGridLayout" name="browseLayout">
<item row="3" column="2">
<widget class="QLineEdit" name="resourceDirLineEdit">
<property name="text">
<string/>
</property>
<property name="placeholderText">
<string>Path to resource directory... (optional)</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QPushButton" name="browseOutputButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="configurationLabel">
<property name="text">
<string>Base configuration:</string>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QPushButton" name="browseConfigButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="dramSysLabel">
<property name="text">
<string>DRAMSys:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="outputDirLabel">
<property name="text">
<string>Output directory:</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="dramSysPath">
<property name="placeholderText">
<string>Path to DRAMSys...</string>
</property>
</widget>
</item>
<item row="3" column="3">
<widget class="QPushButton" name="browseResourceDirButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QPushButton" name="browseDramSysButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLineEdit" name="outputDirLineEdit">
<property name="placeholderText">
<string>Path to output directory...</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLineEdit" name="jsonPath">
<property name="placeholderText">
<string>Path to Json configuration...</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="resourceDirectoryLabel">
<property name="text">
<string>Resource directory:</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLabel" name="simulationIdLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Simulation Id:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="simulationId">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QProgressBar" name="progressBar">
<property name="enabled">
<bool>false</bool>
</property>
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="simulateButton">
<property name="text">
<string>Start Simulation</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="stopButton">
<property name="text">
<string>Stop Simulation</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="simConfigTab">
<attribute name="title">
<string>SimConfig</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QTextEdit" name="simConfigTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="mcConfigTab">
<attribute name="title">
<string>McConfig</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<widget class="QTextEdit" name="mcConfigTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="memSpecTab">
<attribute name="title">
<string>MemSpec</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QTextEdit" name="memSpecTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="thermalConfigTab">
<attribute name="title">
<string>ThermalConfig</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QTextEdit" name="thermalConfigTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="traceSetupTab">
<attribute name="title">
<string>TraceSetup</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_7">
<item row="0" column="0">
<widget class="QTextEdit" name="traceSetupTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="addressMappingTab">
<attribute name="title">
<string>AddressMapping</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_9">
<item row="0" column="0">
<widget class="QTextEdit" name="addressMappingTextEdit">
<property name="font">
<font/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="previewTab">
<attribute name="title">
<string>Preview Configuration</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_8">
<item row="0" column="0">
<widget class="QTextEdit" name="previewTextEdit">
<property name="font">
<font/>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="outputTab">
<attribute name="title">
<string>Output</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPlainTextEdit" name="outputPlainTextEdit">
<property name="font">
<font/>
</property>
<property name="lineWrapMode">
<enum>QPlainTextEdit::NoWrap</enum>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="reloadButton">
<property name="text">
<string>Reload</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLineEdit" name="simulationIdLineEdit">
<property name="placeholderText">
<string>Simulation Id</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Save</string>
</property>
<property name="checkable">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<tabstops>
<tabstop>dramSysPath</tabstop>
<tabstop>outputDirLineEdit</tabstop>
<tabstop>jsonPath</tabstop>
<tabstop>resourceDirLineEdit</tabstop>
<tabstop>browseDramSysButton</tabstop>
<tabstop>browseOutputButton</tabstop>
<tabstop>browseConfigButton</tabstop>
<tabstop>browseResourceDirButton</tabstop>
<tabstop>simulateButton</tabstop>
<tabstop>stopButton</tabstop>
<tabstop>tabWidget</tabstop>
<tabstop>reloadButton</tabstop>
<tabstop>simulationIdLineEdit</tabstop>
<tabstop>saveButton</tabstop>
<tabstop>closeButton</tabstop>
<tabstop>simConfigTextEdit</tabstop>
<tabstop>outputPlainTextEdit</tabstop>
<tabstop>memSpecTextEdit</tabstop>
<tabstop>thermalConfigTextEdit</tabstop>
<tabstop>traceSetupTextEdit</tabstop>
<tabstop>addressMappingTextEdit</tabstop>
<tabstop>mcConfigTextEdit</tabstop>
<tabstop>previewTextEdit</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>closeButton</sender>
<signal>clicked()</signal>
<receiver>SimulationDialog</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>836</x>
<y>507</y>
</hint>
<hint type="destinationlabel">
<x>830</x>
<y>575</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -38,197 +38,16 @@
*/
#include "tracefiletab.h"
#include "businessObjects/commentmodel.h"
#include "businessObjects/configmodels.h"
#include "businessObjects/dramTimeDependencies/phasedependenciestracker.h"
#include "businessObjects/traceplotlinemodel.h"
#include "businessObjects/tracetime.h"
#include "queryeditor.h"
#include "traceanalyzer.h"
#include "ui_tracefiletab.h"
#include <QCloseEvent>
#include <QDebug>
#include <QFileDialog>
#include <QFileInfo>
#include "businessObjects/dramTimeDependencies/phasedependenciestracker.h"
#include <QItemDelegate>
#include <QMessageBox>
#include <QStandardItemModel>
#include <QString>
#include <QTextStream>
#include <QtConcurrent/QtConcurrent>
#include <qwt_legend.h>
#include <qwt_plot_canvas.h>
#include <QStandardItem>
#include <qwt_plot_curve.h>
#include <qwt_plot_histogram.h>
#include <qwt_plot_magnifier.h>
#include <qwt_plot_panner.h>
#include <qwt_scale_draw.h>
#include <qwt_scale_widget.h>
#include <fstream>
#include <pybind11/pybind11.h>
TraceFileTab::TraceFileTab(std::string_view traceFilePath,
PythonCaller& pythonCaller,
QWidget* parent) :
QWidget(parent),
traceFilePath(traceFilePath),
ui(new Ui::TraceFileTab),
commentModel(new CommentModel(this)),
navigator(new TraceNavigator(traceFilePath.data(), commentModel, this)),
mcConfigModel(new McConfigModel(navigator->TraceFile(), this)),
memSpecModel(new MemSpecModel(navigator->TraceFile(), this)),
availableRowsModel(new AvailableTracePlotLineModel(navigator->GeneralTraceInfo(), this)),
selectedRowsModel(new SelectedTracePlotLineModel(navigator->GeneralTraceInfo(), this)),
tracePlotLineDataSource(new TracePlotLineDataSource(selectedRowsModel, this)),
depInfosView(new DependencyInfosModel(navigator->TraceFile(), this)),
pythonCaller(pythonCaller),
savingChangesToDB(false)
{
ui->setupUi(this);
std::cout << "Opening new tab for \"" << traceFilePath << "\"" << std::endl;
ui->mcConfigView->setModel(mcConfigModel);
ui->mcConfigView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->memSpecView->setModel(memSpecModel);
ui->memSpecView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->depInfosView->setModel(depInfosView);
ui->depInfosView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setUpTraceSelector();
initNavigatorAndItsDependentWidgets();
setUpFileWatcher(traceFilePath.data());
setUpTraceplotScrollbar();
setUpCommentView();
setUpPossiblePhases();
tracefileChanged();
}
TraceFileTab::~TraceFileTab()
{
delete ui;
}
void TraceFileTab::commitChangesToDB()
{
savingChangesToDB = true;
navigator->commitChangesToDB();
}
void TraceFileTab::exportAsVCD()
{
std::string filename =
QFileDialog::getSaveFileName(this, "Export to VCD", "", "VCD files (*.vcd)").toStdString();
auto dump = PythonCaller::dumpVcd(traceFilePath);
std::ofstream file(filename);
file << dump;
Q_EMIT statusChanged(QString("VCD export finished."));
}
void TraceFileTab::setUpTraceSelector()
{
ui->availableTreeView->setModel(availableRowsModel);
ui->availableTreeView->setSelectionModel(availableRowsModel->selectionModel());
ui->availableTreeView->installEventFilter(availableRowsModel);
ui->selectedTreeView->setModel(selectedRowsModel);
ui->selectedTreeView->setSelectionModel(selectedRowsModel->selectionModel());
ui->selectedTreeView->installEventFilter(selectedRowsModel);
connect(availableRowsModel,
&AvailableTracePlotLineModel::returnPressed,
selectedRowsModel,
&SelectedTracePlotLineModel::addIndexesFromAvailableModel);
connect(ui->availableTreeView,
&QAbstractItemView::doubleClicked,
availableRowsModel,
&AvailableTracePlotLineModel::itemsDoubleClicked);
connect(ui->selectedTreeView,
&QAbstractItemView::doubleClicked,
selectedRowsModel,
&SelectedTracePlotLineModel::itemsDoubleClicked);
connect(selectedRowsModel,
&QAbstractItemModel::dataChanged,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
connect(selectedRowsModel,
&QAbstractItemModel::rowsInserted,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
connect(selectedRowsModel,
&QAbstractItemModel::rowsRemoved,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
}
void TraceFileTab::setUpTraceplotScrollbar()
{
QObject::connect(ui->traceplotScrollbar,
SIGNAL(valueChanged(int)),
ui->traceplot,
SLOT(verticalScrollbarChanged(int)));
}
void TraceFileTab::initNavigatorAndItsDependentWidgets()
{
ui->traceplot->init(navigator, ui->traceplotScrollbar, tracePlotLineDataSource, commentModel);
ui->traceScroller->init(navigator, ui->traceplot, tracePlotLineDataSource);
connect(this,
SIGNAL(colorGroupingChanged(ColorGrouping)),
ui->traceScroller,
SLOT(colorGroupingChanged(ColorGrouping)));
ui->selectedTransactionTree->init(navigator);
// ui->debugMessages->init(navigator,ui->traceplot);
ui->bandwidthPlot->canvas()->installEventFilter(this);
ui->powerPlot->canvas()->installEventFilter(this);
ui->bufferPlot->canvas()->installEventFilter(this);
}
void TraceFileTab::setUpFileWatcher(QString path)
{
fileWatcher = new QFileSystemWatcher(QStringList(path), this);
QObject::connect(fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(tracefileChanged()));
}
void TraceFileTab::setUpCommentView()
{
ui->commentView->setModel(commentModel);
ui->commentView->setSelectionModel(commentModel->selectionModel());
ui->commentView->installEventFilter(commentModel);
ui->commentView->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ui->commentView,
&QTableView::customContextMenuRequested,
commentModel,
&CommentModel::openContextMenu);
QObject::connect(commentModel,
&CommentModel::editTriggered,
ui->commentView,
[=](const QModelIndex& index)
{
ui->tabWidget->setCurrentWidget(ui->tabComments);
ui->commentView->edit(index);
ui->commentView->scrollTo(index);
});
QObject::connect(
ui->commentView, &QTableView::doubleClicked, commentModel, &CommentModel::rowDoubleClicked);
}
void TraceFileTab::setUpPossiblePhases()
{
@@ -244,94 +63,6 @@ void TraceFileTab::setUpPossiblePhases()
ConfigurationFactory::deviceSupported(navigator->TraceFile()));
}
void TraceFileTab::tracefileChanged()
{
if (savingChangesToDB == true)
{
// Database has changed due to user action (e.g., saving comments).
// No need to disable the "Save changes to DB" menu.
savingChangesToDB = false;
Q_EMIT statusChanged(QString("Changes saved "));
}
else
{
// External event changed the database file (e.g., the database file
// was overwritten when running a new test).
// The "Save changes to DB" menu must be disabled to avoid saving
// changes to a corrupted or inconsistent file.
Q_EMIT statusChanged(QString("At least one database has changed on disk "));
}
navigator->refreshData();
}
void TraceFileTab::closeEvent(QCloseEvent* event)
{
if (navigator->existChangesToCommit())
{
QMessageBox saveDialog;
saveDialog.setWindowTitle(QFileInfo(traceFilePath.data()).baseName());
saveDialog.setText("The trace file has been modified.");
saveDialog.setInformativeText(
"Do you want to save your changes?<br><b>Unsaved changes will be lost.</b>");
saveDialog.setStandardButtons(QMessageBox::Save | QMessageBox::Discard |
QMessageBox::Cancel);
saveDialog.setDefaultButton(QMessageBox::Save);
saveDialog.setIcon(QMessageBox::Warning);
int returnCode = saveDialog.exec();
switch (returnCode)
{
case QMessageBox::Cancel:
event->ignore();
break;
case QMessageBox::Discard:
event->accept();
break;
case QMessageBox::Save:
commitChangesToDB();
event->accept();
break;
};
}
else
event->accept();
}
traceTime TraceFileTab::getCurrentTraceTime() const
{
return navigator->CurrentTraceTime();
}
void TraceFileTab::navigateToTime(traceTime time)
{
navigator->navigateToTime(time);
}
traceTime TraceFileTab::getZoomLevel() const
{
TracePlot* traceplot = static_cast<TracePlot*>(ui->traceplot);
return traceplot->ZoomLevel();
}
void TraceFileTab::setZoomLevel(traceTime zoomLevel)
{
TracePlot* traceplot = static_cast<TracePlot*>(ui->traceplot);
TraceScroller* tracescroller = static_cast<TraceScroller*>(ui->traceScroller);
traceplot->setZoomLevel(zoomLevel);
tracescroller->tracePlotZoomChanged();
}
std::shared_ptr<AbstractTracePlotLineModel::Node> TraceFileTab::saveTraceSelectorState() const
{
return selectedRowsModel->getClonedRootNode();
}
void TraceFileTab::restoreTraceSelectorState(
std::shared_ptr<AbstractTracePlotLineModel::Node> rootNode)
{
selectedRowsModel->setRootNode(std::move(rootNode));
}
class ItemDelegate : public QItemDelegate
{
public:
@@ -372,32 +103,6 @@ void TraceFileTab::on_latencyTreeView_doubleClicked(const QModelIndex& index)
}
}
bool TraceFileTab::eventFilter(QObject* object, QEvent* event)
{
if (auto canvas = qobject_cast<QwtPlotCanvas*>(object))
{
if (event->type() == QEvent::MouseButtonDblClick)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() != Qt::LeftButton)
return false;
QwtPlot* plot = canvas->plot();
double realTime = plot->invTransform(QwtPlot::xBottom, mouseEvent->x());
// Convert from seconds to picoseconds
traceTime time = realTime * 1000 * 1000 * 1000 * 1000;
navigator->navigateToTime(time);
return true;
}
}
return QWidget::eventFilter(object, event);
}
void TraceFileTab::on_calculateDependencies_clicked()
{
std::vector<QString> dependencyFilter;
@@ -490,7 +195,6 @@ void TraceFileTab::on_startLatencyAnalysis_clicked()
void TraceFileTab::on_startPowerAnalysis_clicked()
{
qDebug() << "Power Analysis";
QSqlDatabase db = navigator->TraceFile().getDatabase();
QSqlQuery query(db);
@@ -502,11 +206,13 @@ void TraceFileTab::on_startPowerAnalysis_clicked()
QwtPlotCurve* cur = new QwtPlotCurve("Speed");
QVector<QPointF>* samples = new QVector<QPointF>;
double maxPower = 0.0;
while (query.next())
{
double time = query.value(0).toDouble();
double power = query.value(1).toDouble();
samples->push_back(QPointF(time, power));
maxPower = std::max(maxPower, power);
}
// ui->powerPlot->setAxisTitle(QwtPlot::xBottom,"Time");
@@ -519,6 +225,12 @@ void TraceFileTab::on_startPowerAnalysis_clicked()
cur->attach(ui->powerPlot);
cur->setPen(QPen(QColor(255, 0, 0)));
ui->powerPlot->setAxisTitle(0, "Power [mW]");
ui->powerPlot->setAxisScale(0, 0.0, maxPower);
QwtText axisTitle0("Time [s]");
axisTitle0.setFont(ui->powerPlot->axisTitle(QwtPlot::xBottom).font());
ui->powerPlot->setAxisTitle(QwtPlot::xBottom, axisTitle0);
QwtPlotMagnifier* mag1 = new QwtPlotMagnifier(ui->powerPlot->canvas());
mag1->setAxisEnabled(QwtPlot::xBottom, true);
mag1->setAxisEnabled(QwtPlot::yLeft, false);

View File

@@ -6,4 +6,4 @@ FOREACH(sub_dir ${sub_dirs})
IF(IS_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/${sub_dir}")
add_subdirectory(${sub_dir})
ENDIF()
ENDFOREACH()
ENDFOREACH()

View File

@@ -0,0 +1,104 @@
# Copyright (c) 2020, RPTU Kaiserslautern-Landau
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors:
# Matthias Jung
# Lukas Steiner
# Derek Christ
# Iron Prando da Silva
########################################
### TraceAnalyzer ###
########################################
project(TraceAnalyzer)
file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS *.cpp)
file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS *.h;*.hpp)
# Add Python3 Dependency:
find_package(Python3 COMPONENTS Development Interpreter)
FetchContent_Declare(
pybind11
URL https://github.com/pybind/pybind11/archive/refs/tags/v2.13.1.zip
)
FetchContent_MakeAvailable(pybind11)
# Add QWT Dependency:
find_library(QWT_LIBRARY NAMES "qwt" "qwt-qt5" PATHS
"$ENV{QWT_HOME}/lib"
"/opt/homebrew/opt/qwt-qt5/lib"
)
find_path(QWT_INCLUDE_DIRS NAMES "qwt_plot.h" PATHS
"$ENV{QWT_HOME}/include"
"/usr/include/qwt-qt5"
"/usr/include/qwt"
"/opt/homebrew/opt/qwt-qt5/include"
"/opt/homebrew/opt/qwt-qt5/lib/qwt.framework/Headers"
)
# Add QT Library:
if (APPLE)
set(Qt5_DIR "/opt/homebrew/opt/qt@5/lib/cmake/Qt5")
endif(APPLE)
find_package(Qt5 COMPONENTS Core Gui Widgets Sql REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(TraceAnalyzer ${SOURCE_FILES} ${HEADER_FILES})
target_include_directories(TraceAnalyzer
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${QWT_INCLUDE_DIRS}
)
target_link_libraries(TraceAnalyzer
PRIVATE
pybind11::embed
${QWT_LIBRARY}
Qt5::Widgets
Qt5::Sql
DRAMSys::util
DRAMSys::config
)
set(DRAMSYS_TRACE_ANALYZER_EXTENSION_DIR "${CMAKE_SOURCE_DIR}/extensions/apps/traceAnalyzer")
target_compile_definitions(${PROJECT_NAME}
PRIVATE
DRAMSYS_TRACE_ANALYZER_EXTENSION_DIR="${DRAMSYS_TRACE_ANALYZER_EXTENSION_DIR}"
)
build_source_group()

View File

@@ -277,7 +277,7 @@ const std::vector<CommentModel::Comment>& CommentModel::getComments() const
traceTime CommentModel::getTimeFromIndex(const QModelIndex& index) const
{
Q_ASSERT(index.row() > 0 && comments.size() > static_cast<unsigned>(index.row()));
Q_ASSERT(index.row() >= 0 && comments.size() > static_cast<unsigned>(index.row()));
return comments[index.row()].time;
}

View File

@@ -36,8 +36,11 @@
#ifndef CONFIGMODELS_H
#define CONFIGMODELS_H
#include "../data/tracedb.h"
#include "phases/dependencyinfos.h"
#include "data/tracedb.h"
#ifdef EXTENSION_ENABLED
#include "businessObjects/phases/dependencyinfos.h"
#endif
#include <QAbstractTableModel>
#include <utility>

View File

@@ -217,6 +217,7 @@ void Phase::drawPhaseDependencies(traceTime begin,
QPoint depLineTo(static_cast<int>(xMap.transform(begin /* + (end + offset - begin)/4*/)),
static_cast<int>(yVal));
#ifdef EXTENSION_ENABLED
for (const auto& dep : mDependencies)
{
if (dep->isVisible())
@@ -231,6 +232,7 @@ void Phase::drawPhaseDependencies(traceTime begin,
invisibleDeps += 1;
}
}
#endif
if (invisibleDeps > 0)
{
@@ -418,7 +420,9 @@ Phase::PhaseSymbol Phase::getPhaseSymbol() const
return PhaseSymbol::Hexagon;
}
#ifdef EXTENSION_ENABLED
void Phase::addDependency(const std::shared_ptr<PhaseDependency>& dependency)
{
mDependencies.push_back(dependency);
}
#endif

View File

@@ -39,7 +39,11 @@
#ifndef BANKPHASE_H
#define BANKPHASE_H
#ifdef EXTENSION_ENABLED
#include "businessObjects/phases/phasedependency.h"
#endif
#include "businessObjects/timespan.h"
#include "presentation/tracedrawingproperties.h"
#include "presentation/util/colorgenerator.h"
@@ -141,7 +145,9 @@ public:
virtual QString Name() const = 0;
#ifdef EXTENSION_ENABLED
void addDependency(const std::shared_ptr<PhaseDependency>& dependency);
#endif
protected:
ID id;
@@ -152,7 +158,9 @@ protected:
traceTime clk;
std::weak_ptr<Transaction> transaction;
std::vector<Timespan> spansOnCommandBus;
#ifdef EXTENSION_ENABLED
std::vector<std::shared_ptr<PhaseDependency>> mDependencies;
#endif
double hexagonHeight;
TextPositioning captionPosition;

View File

@@ -167,6 +167,7 @@ bool TraceDB::checkDependencyTableExists()
return exists;
}
#ifdef EXTENSION_ENABLED
void TraceDB::updateDependenciesInTimespan(const Timespan& span)
{
if (checkDependencyTableExists())
@@ -177,6 +178,7 @@ void TraceDB::updateDependenciesInTimespan(const Timespan& span)
mUpdateDependenciesFromQuery(selectDependenciesByTimespan);
}
}
#endif
// TODO Remove exception
std::shared_ptr<Transaction> TraceDB::getTransactionByID(ID id)
@@ -498,6 +500,7 @@ std::vector<CommentModel::Comment> TraceDB::getDebugMessagesInTimespan(const Tim
return parseCommentsFromQuery(selectDebugMessagesByTimespanWithLimit);
}
#ifdef EXTENSION_ENABLED
DependencyInfos TraceDB::getDependencyInfos(DependencyInfos::Type infoType)
{
DependencyInfos dummy;
@@ -551,6 +554,7 @@ DependencyInfos TraceDB::getDependencyInfos(DependencyInfos::Type infoType)
return dummy;
}
#endif
QSqlDatabase TraceDB::getDatabase() const
{
@@ -643,6 +647,7 @@ TraceDB::parseTransactionsFromQuery(QSqlQuery& query, bool updateVisiblePhases)
return result;
}
#ifdef EXTENSION_ENABLED
void TraceDB::mUpdateDependenciesFromQuery(QSqlQuery& query)
{
DependencyType type;
@@ -689,6 +694,7 @@ void TraceDB::mUpdateDependenciesFromQuery(QSqlQuery& query)
}
}
}
#endif
std::vector<CommentModel::Comment> TraceDB::parseCommentsFromQuery(QSqlQuery& query)
{
@@ -701,6 +707,7 @@ std::vector<CommentModel::Comment> TraceDB::parseCommentsFromQuery(QSqlQuery& qu
return result;
}
#ifdef EXTENSION_ENABLED
DependencyInfos TraceDB::parseDependencyInfos(QSqlQuery& query,
const DependencyInfos::Type infoType)
{
@@ -715,6 +722,7 @@ DependencyInfos TraceDB::parseDependencyInfos(QSqlQuery& query,
return infos;
}
#endif
void TraceDB::executeQuery(QSqlQuery query)
{

View File

@@ -41,10 +41,14 @@
#define TRACEDB_H
#include "QueryTexts.h"
#ifdef EXTENSION_ENABLED
#include "businessObjects/phases/dependencyinfos.h"
#endif
#include "businessObjects/commandlengths.h"
#include "businessObjects/commentmodel.h"
#include "businessObjects/generalinfo.h"
#include "businessObjects/phases/dependencyinfos.h"
#include "businessObjects/phases/phasefactory.h"
#include "businessObjects/transaction.h"
#include <QSqlDatabase>
@@ -69,11 +73,13 @@ public:
void updateComments(const std::vector<CommentModel::Comment>& comments);
void updateFileDescription(const QString& description);
void updateDependenciesInTimespan(const Timespan& span);
void refreshData();
const GeneralInfo& getGeneralInfo() const { return generalInfo; }
#ifdef EXTENSION_ENABLED
void updateDependenciesInTimespan(const Timespan& span);
#endif
const GeneralInfo& getGeneralInfo() const { return generalInfo; }
const CommandLengths& getCommandLengths() const { return commandLengths; }
std::vector<std::shared_ptr<Transaction>>
@@ -97,8 +103,9 @@ public:
unsigned int limit);
bool checkDependencyTableExists();
#ifdef EXTENSION_ENABLED
DependencyInfos getDependencyInfos(DependencyInfos::Type infoType);
#endif
QSqlDatabase getDatabase() const;
private:
@@ -129,9 +136,11 @@ private:
parseTransactionsFromQuery(QSqlQuery& query, bool updateVisiblePhases = false);
static std::vector<CommentModel::Comment> parseCommentsFromQuery(QSqlQuery& query);
#ifdef EXTENSION_ENABLED
void mUpdateDependenciesFromQuery(QSqlQuery& query);
static DependencyInfos parseDependencyInfos(QSqlQuery& query,
const DependencyInfos::Type infoType);
#endif
void executeScriptFile(const QString& fileName);
void dropAndCreateTables();

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2021, RPTU Kaiserslautern-Landau
* Copyright (c) 2024, RPTU Kaiserslautern-Landau
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -33,70 +33,32 @@
* Derek Christ
*/
#ifndef SIMULATIONDIALOG_H
#define SIMULATIONDIALOG_H
#ifndef EXTENSION_H
#define EXTENSION_H
#include "ui_simulationdialog.h"
#include <QLabel>
#include <QMessageBox>
#include "DRAMSys/config/DRAMSysConfiguration.h"
inline constexpr std::string_view EXTENSION_DISCLAIMER =
"This feature is part of the full version of Trace Analyzer. For more information, please "
"contact <a href=\"mailto:DRAMSys@iese.fraunhofer.de\">DRAMSys@iese.fraunhofer.de</a>.";
#include <QFileInfo>
#include <QPointer>
#include <QProcess>
#include <QSyntaxHighlighter>
#include <QTemporaryFile>
#include <QWidget>
namespace Ui
inline void showExtensionDisclaimerMessageBox()
{
class SimulationDialog;
QMessageBox box;
box.setText("Feature unavailable");
box.setInformativeText(EXTENSION_DISCLAIMER.data());
box.setIcon(QMessageBox::Information);
box.exec();
}
class SimulationDialog : public QWidget
inline QLabel* disclaimerLabel()
{
Q_OBJECT
auto* label = new QLabel;
label->setText(EXTENSION_DISCLAIMER.data());
label->setAlignment(Qt::AlignHCenter);
label->setWordWrap(true);
return label;
}
public:
explicit SimulationDialog(QWidget* parent = nullptr);
signals:
void openFileRequested(const QString& path);
private Q_SLOTS:
void on_browseDramSysButton_clicked();
void on_browseConfigButton_clicked();
void on_browseOutputButton_clicked();
void on_browseResourceDirButton_clicked();
void on_simulateButton_clicked();
void on_reloadButton_clicked();
void on_saveButton_clicked();
void on_stopButton_clicked();
private:
void loadConfigurationFromPath();
void loadConfigurationFromTextFields();
void loadConfiguration();
void loadSimConfig();
void loadMcConfig();
void loadMemSpec();
void loadAddressMapping();
void loadTraceSetup();
void loadPreview();
void showStopButton(bool val);
void saveConfiguration(QFile& file);
void processMessage(const std::string& msg);
QFileInfoList getSimulationResults();
void openSimulationResults(const QFileInfoList& fileInfos);
QTemporaryFile temporaryConfigurationFile;
DRAMSys::Config::Configuration configuration;
QPointer<QProcess> simulatorProcess;
Ui::SimulationDialog* ui;
};
#endif
#endif // EXTENSION_H

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

@@ -33,6 +33,7 @@
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
*/
#include "traceanalyzer.h"
@@ -48,16 +49,15 @@
int main(int argc, char* argv[])
{
std::cout << argv[0] << std::endl;
QApplication a(argc, argv);
QIcon icon(QStringLiteral(":/icon"));
a.setWindowIcon(icon);
a.setApplicationName(QStringLiteral("TraceAnalyzer"));
a.setApplicationDisplayName(QStringLiteral("Trace Analyzer"));
QApplication::setWindowIcon(icon);
QApplication::setApplicationName(QStringLiteral("TraceAnalyzer"));
QApplication::setApplicationDisplayName(QStringLiteral("Trace Analyzer"));
std::filesystem::path traceAnalyzerDir = DRAMSYS_TRACEANALYZER_DIR;
std::filesystem::path modulesDir = traceAnalyzerDir / "scripts";
std::filesystem::path extensionDir = DRAMSYS_TRACE_ANALYZER_EXTENSION_DIR;
std::filesystem::path modulesDir = extensionDir / "scripts";
pybind11::scoped_interpreter guard;
@@ -92,12 +92,10 @@ int main(int argc, char* argv[])
TraceAnalyzer analyzer(arguments);
analyzer.show();
return a.exec();
}
else
{
TraceAnalyzer analyzer;
analyzer.show();
return a.exec();
return QApplication::exec();
}
TraceAnalyzer analyzer;
analyzer.show();
return QApplication::exec();
}

View File

@@ -286,6 +286,11 @@ void TracePlot::setUpActions()
dependenciesGroup->addAction(disabledDependencies);
dependenciesGroup->addAction(selectedDependencies);
dependenciesGroup->addAction(allDependencies);
dependenciesGroup->addAction(switchDrawDependencyTextsOption);
#ifndef EXTENSION_ENABLED
dependenciesGroup->setEnabled(false);
#endif
setUpContextMenu();
}
@@ -628,10 +633,13 @@ void TracePlot::currentTraceTimeChanged()
transactions =
navigator->TraceFile().getTransactionsInTimespan(GetCurrentTimespan(), drawDependencies);
#ifdef EXTENSION_ENABLED
if (drawDependencies)
{
navigator->TraceFile().updateDependenciesInTimespan(GetCurrentTimespan());
}
#endif
setAxisScale(xBottom, GetCurrentTimespan().Begin(), GetCurrentTimespan().End());

View File

@@ -220,10 +220,12 @@ void TraceScroller::currentTraceTimeChanged()
Timespan span = GetCurrentTimespan();
transactions = navigator->TraceFile().getTransactionsInTimespan(span, drawDependencies);
#ifdef EXTENSION_ENABLED
if (drawDependencies)
{
navigator->TraceFile().updateDependenciesInTimespan(span);
}
#endif
setAxisScale(xBottom, span.Begin(), span.End());
replot();

View File

@@ -37,7 +37,7 @@
*/
#include "traceanalyzer.h"
#include "simulationdialog.h"
#include "extensionDisclaimer.h"
#include "tracefiletab.h"
#include "ui_traceanalyzer.h"
@@ -53,7 +53,10 @@ void TraceAnalyzer::setUpStatusBar()
statusBar()->addWidget(statusLabel);
}
void TraceAnalyzer::setUpGui()
TraceAnalyzer::TraceAnalyzer(QWidget* parent) :
QMainWindow(parent),
evaluationTool(pythonCaller),
ui(new Ui::TraceAnalyzer)
{
ui->setupUi(this);
setUpStatusBar();
@@ -62,21 +65,8 @@ void TraceAnalyzer::setUpGui()
QObject::connect(ui->actionAbout_Qt, &QAction::triggered, qApp, &QApplication::aboutQt);
}
TraceAnalyzer::TraceAnalyzer(QWidget* parent) :
QMainWindow(parent),
evaluationTool(pythonCaller),
ui(new Ui::TraceAnalyzer)
TraceAnalyzer::TraceAnalyzer(QSet<QString> paths, QWidget* parent) : TraceAnalyzer(parent)
{
setUpGui();
}
TraceAnalyzer::TraceAnalyzer(QSet<QString> paths, QWidget* parent) :
QMainWindow(parent),
evaluationTool(pythonCaller),
ui(new Ui::TraceAnalyzer)
{
setUpGui();
for (const QString& path : paths)
openTracefileTab(path);
}
@@ -99,7 +89,7 @@ void TraceAnalyzer::on_actionOpen_triggered()
TraceFileTab* TraceAnalyzer::createTraceFileTab(const QString& path)
{
TraceFileTab* traceFileTab = new TraceFileTab(path.toStdString(), pythonCaller, this);
auto* traceFileTab = new TraceFileTab(path.toStdString(), pythonCaller, this);
connect(traceFileTab, &TraceFileTab::statusChanged, this, &TraceAnalyzer::statusChanged);
@@ -131,7 +121,6 @@ void TraceAnalyzer::on_menuFile_aboutToShow()
ui->actionReload->setEnabled(tabsOpen);
ui->actionReload_all->setEnabled(tabsOpen);
ui->actionExportAsVCD->setEnabled(tabsOpen);
ui->actionTest->setEnabled(tabsOpen);
ui->actionMetrics->setEnabled(tabsOpen);
ui->actionClose->setEnabled(tabsOpen);
ui->actionClose_all->setEnabled(tabsOpen);
@@ -139,7 +128,7 @@ void TraceAnalyzer::on_menuFile_aboutToShow()
void TraceAnalyzer::closeTab(int index)
{
TraceFileTab* traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
auto* traceFileTab = dynamic_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
if (traceFileTab->close())
{
@@ -169,7 +158,7 @@ void TraceAnalyzer::on_actionClose_all_triggered()
void TraceAnalyzer::reloadTab(int index)
{
auto traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
auto* traceFileTab = dynamic_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
QString traceFile = traceFileTab->getPathToTraceFile();
traceTime time = traceFileTab->getCurrentTraceTime();
@@ -212,7 +201,7 @@ void TraceAnalyzer::on_actionReload_all_triggered()
void TraceAnalyzer::on_actionSave_triggered()
{
auto traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->currentWidget());
auto* traceFileTab = dynamic_cast<TraceFileTab*>(ui->traceFileTabs->currentWidget());
traceFileTab->commitChangesToDB();
this->statusChanged(QString("Saved database ") +
@@ -226,14 +215,19 @@ void TraceAnalyzer::on_actionSave_all_triggered()
// Changes in the database files will trigger the file watchers from
// the TraceFileTab class. They generate signals connected to
// TraceAnalyzer::statusChanged().
TraceFileTab* traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
auto* traceFileTab = dynamic_cast<TraceFileTab*>(ui->traceFileTabs->widget(index));
traceFileTab->commitChangesToDB();
}
}
void TraceAnalyzer::on_actionExportAsVCD_triggered()
{
TraceFileTab* traceFileTab = static_cast<TraceFileTab*>(ui->traceFileTabs->currentWidget());
#ifndef EXTENSION_ENABLED
showExtensionDisclaimerMessageBox();
return;
#endif
auto* traceFileTab = dynamic_cast<TraceFileTab*>(ui->traceFileTabs->currentWidget());
traceFileTab->exportAsVCD();
}
@@ -244,6 +238,11 @@ void TraceAnalyzer::statusChanged(const QString& message)
void TraceAnalyzer::on_actionMetrics_triggered()
{
#ifndef EXTENSION_ENABLED
showExtensionDisclaimerMessageBox();
return;
#endif
evaluationTool.raise();
evaluationTool.activateWindow();
evaluationTool.showAndEvaluateMetrics(openedTraceFiles.values());
@@ -254,12 +253,15 @@ void TraceAnalyzer::on_actionAbout_triggered()
QMessageBox::about(
this,
QStringLiteral("DRAMSys"),
QStringLiteral("<b>DRAMSys4.0</b> is a flexible DRAM subsystem design space exploration "
"framework based on SystemC "
"TLM-2.0. It was developed at the <a "
"href=\"https://ems.eit.uni-kl.de/en/start/\">Microelectronic Systems "
"Design Research Group</a> and <a "
"href=\"https://www.iese.fraunhofer.de/en.html\">Fraunhofer IESE</a>."));
QStringLiteral(
"<b>DRAMSys5.0</b> is a flexible DRAM subsystem design space exploration "
"framework based on SystemC "
"TLM-2.0. It was developed by the <a "
"href=\"https://ems.eit.uni-kl.de/en/start/\">Microelectronic Systems "
"Design Research Group</a>, by <a "
"href=\"https://www.iese.fraunhofer.de/en.html\">Fraunhofer IESE</a> and by the <a "
"href=\"https://www.informatik.uni-wuerzburg.de/ce\">Computer Engineering Group</a> at "
"<a href=\"https://www.uni-wuerzburg.de/en/home\">JMU Würzburg</a>."));
}
void TraceAnalyzer::closeEvent(QCloseEvent* event)
@@ -276,16 +278,3 @@ void TraceAnalyzer::closeEvent(QCloseEvent* event)
event->accept();
}
void TraceAnalyzer::on_actionSimulate_triggered()
{
SimulationDialog* simulationDialog = new SimulationDialog(this);
simulationDialog->setWindowFlag(Qt::Window);
QObject::connect(simulationDialog,
&SimulationDialog::openFileRequested,
this,
&TraceAnalyzer::openTracefileTab);
simulationDialog->show();
}

View File

@@ -63,7 +63,6 @@ public:
~TraceAnalyzer();
void setUpStatusBar();
void setUpGui();
protected:
void closeEvent(QCloseEvent* event) override;
@@ -93,7 +92,6 @@ private Q_SLOTS:
void on_actionClose_triggered();
void on_actionClose_all_triggered();
void on_actionAbout_triggered();
void on_actionSimulate_triggered();
public Q_SLOTS:
void statusChanged(const QString& message);

View File

@@ -49,7 +49,7 @@
<x>0</x>
<y>0</y>
<width>800</width>
<height>34</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
@@ -78,14 +78,7 @@
<addaction name="actionAbout"/>
<addaction name="actionAbout_Qt"/>
</widget>
<widget class="QMenu" name="menuRun">
<property name="title">
<string>&amp;Run</string>
</property>
<addaction name="actionSimulate"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuRun"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
@@ -133,32 +126,11 @@
<string>Ctrl+Shift+W</string>
</property>
</action>
<action name="actionInfo">
<property name="text">
<string>&amp;Info</string>
</property>
</action>
<action name="actionAbout">
<property name="text">
<string>&amp;About DRAMSys</string>
</property>
</action>
<action name="actionPreferences">
<property name="text">
<string>Preferences</string>
</property>
<property name="shortcut">
<string>Ctrl+P</string>
</property>
</action>
<action name="actionTest">
<property name="text">
<string>&amp;Test</string>
</property>
<property name="shortcut">
<string>Ctrl+T</string>
</property>
</action>
<action name="actionMetrics">
<property name="text">
<string>&amp;Metrics</string>
@@ -232,15 +204,6 @@
<string>Save &amp;as...</string>
</property>
</action>
<action name="actionSimulate">
<property name="icon">
<iconset theme="system-run">
<normaloff>.</normaloff>.</iconset>
</property>
<property name="text">
<string>&amp;Simulate...</string>
</property>
</action>
<action name="actionAbout_Qt">
<property name="text">
<string>About &amp;Qt</string>

View File

@@ -0,0 +1,364 @@
/*
* Copyright (c) 2015, RPTU Kaiserslautern-Landau
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Authors:
* Janik Schlemminger
* Robert Gernhardt
* Matthias Jung
* Derek Christ
* Iron Prando da Silva
*/
#include "tracefiletab.h"
#include "businessObjects/pythoncaller.h"
#include "extensionDisclaimer.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QMouseEvent>
#include <qwt_plot_canvas.h>
#include <fstream>
TraceFileTab::TraceFileTab(std::string_view traceFilePath,
PythonCaller& pythonCaller,
QWidget* parent) :
QWidget(parent),
traceFilePath(traceFilePath),
ui(new Ui::TraceFileTab),
commentModel(new CommentModel(this)),
navigator(new TraceNavigator(traceFilePath.data(), commentModel, this)),
mcConfigModel(new McConfigModel(navigator->TraceFile(), this)),
memSpecModel(new MemSpecModel(navigator->TraceFile(), this)),
availableRowsModel(new AvailableTracePlotLineModel(navigator->GeneralTraceInfo(), this)),
selectedRowsModel(new SelectedTracePlotLineModel(navigator->GeneralTraceInfo(), this)),
tracePlotLineDataSource(new TracePlotLineDataSource(selectedRowsModel, this)),
#ifdef EXTENSION_ENABLED
depInfosView(new DependencyInfosModel(navigator->TraceFile(), this)),
#endif
pythonCaller(pythonCaller),
savingChangesToDB(false)
{
ui->setupUi(this);
std::cout << "Opening new tab for \"" << traceFilePath << "\"" << std::endl;
ui->mcConfigView->setModel(mcConfigModel);
ui->mcConfigView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui->memSpecView->setModel(memSpecModel);
ui->memSpecView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#ifdef EXTENSION_ENABLED
ui->depInfosView->setModel(depInfosView);
ui->depInfosView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
#endif
setUpTraceSelector();
initNavigatorAndItsDependentWidgets();
setUpFileWatcher(traceFilePath.data());
setUpTraceplotScrollbar();
setUpCommentView();
#ifdef EXTENSION_ENABLED
setUpPossiblePhases();
#else
addDisclaimer();
#endif
tracefileChanged();
}
TraceFileTab::~TraceFileTab()
{
delete ui;
}
void TraceFileTab::commitChangesToDB()
{
savingChangesToDB = true;
navigator->commitChangesToDB();
}
void TraceFileTab::exportAsVCD()
{
std::string filename =
QFileDialog::getSaveFileName(this, "Export to VCD", "", "VCD files (*.vcd)").toStdString();
auto dump = PythonCaller::dumpVcd(traceFilePath);
std::ofstream file(filename);
file << dump;
Q_EMIT statusChanged(QString("VCD export finished."));
}
void TraceFileTab::setUpTraceSelector()
{
ui->availableTreeView->setModel(availableRowsModel);
ui->availableTreeView->setSelectionModel(availableRowsModel->selectionModel());
ui->availableTreeView->installEventFilter(availableRowsModel);
ui->selectedTreeView->setModel(selectedRowsModel);
ui->selectedTreeView->setSelectionModel(selectedRowsModel->selectionModel());
ui->selectedTreeView->installEventFilter(selectedRowsModel);
connect(availableRowsModel,
&AvailableTracePlotLineModel::returnPressed,
selectedRowsModel,
&SelectedTracePlotLineModel::addIndexesFromAvailableModel);
connect(ui->availableTreeView,
&QAbstractItemView::doubleClicked,
availableRowsModel,
&AvailableTracePlotLineModel::itemsDoubleClicked);
connect(ui->selectedTreeView,
&QAbstractItemView::doubleClicked,
selectedRowsModel,
&SelectedTracePlotLineModel::itemsDoubleClicked);
connect(selectedRowsModel,
&QAbstractItemModel::dataChanged,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
connect(selectedRowsModel,
&QAbstractItemModel::rowsInserted,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
connect(selectedRowsModel,
&QAbstractItemModel::rowsRemoved,
tracePlotLineDataSource,
&TracePlotLineDataSource::updateModel);
}
void TraceFileTab::setUpTraceplotScrollbar()
{
QObject::connect(ui->traceplotScrollbar,
SIGNAL(valueChanged(int)),
ui->traceplot,
SLOT(verticalScrollbarChanged(int)));
}
void TraceFileTab::initNavigatorAndItsDependentWidgets()
{
ui->traceplot->init(navigator, ui->traceplotScrollbar, tracePlotLineDataSource, commentModel);
ui->traceScroller->init(navigator, ui->traceplot, tracePlotLineDataSource);
connect(this,
SIGNAL(colorGroupingChanged(ColorGrouping)),
ui->traceScroller,
SLOT(colorGroupingChanged(ColorGrouping)));
ui->selectedTransactionTree->init(navigator);
// ui->debugMessages->init(navigator,ui->traceplot);
ui->bandwidthPlot->canvas()->installEventFilter(this);
ui->powerPlot->canvas()->installEventFilter(this);
ui->bufferPlot->canvas()->installEventFilter(this);
}
void TraceFileTab::setUpFileWatcher(QString path)
{
fileWatcher = new QFileSystemWatcher(QStringList(path), this);
QObject::connect(fileWatcher, SIGNAL(fileChanged(QString)), this, SLOT(tracefileChanged()));
}
void TraceFileTab::setUpCommentView()
{
ui->commentView->setModel(commentModel);
ui->commentView->setSelectionModel(commentModel->selectionModel());
ui->commentView->installEventFilter(commentModel);
ui->commentView->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(ui->commentView,
&QTableView::customContextMenuRequested,
commentModel,
&CommentModel::openContextMenu);
QObject::connect(commentModel,
&CommentModel::editTriggered,
ui->commentView,
[=](const QModelIndex& index)
{
ui->tabWidget->setCurrentWidget(ui->tabComments);
ui->commentView->edit(index);
ui->commentView->scrollTo(index);
});
QObject::connect(
ui->commentView, &QTableView::doubleClicked, commentModel, &CommentModel::rowDoubleClicked);
}
void TraceFileTab::addDisclaimer()
{
// Latency analysis
auto* latencyDisclaimerLabel = disclaimerLabel();
ui->latencyLayout->insertWidget(0, latencyDisclaimerLabel);
ui->latencyAnalysisProgressBar->setEnabled(false);
ui->startLatencyAnalysis->setEnabled(false);
ui->latencyPlot->setEnabled(false);
ui->latencyTreeView->setEnabled(false);
// Power analysis
auto* powerDisclaimerLabel = disclaimerLabel();
ui->powerLayout->insertWidget(0, powerDisclaimerLabel);
ui->startPowerAnalysis->setEnabled(false);
ui->powerBox->setEnabled(false);
ui->bandwidthBox->setEnabled(false);
ui->bufferBox->setEnabled(false);
// Dependencies
auto* dependenciesDisclaimerLabel = disclaimerLabel();
ui->verticalLayout_depInfos->insertWidget(0, dependenciesDisclaimerLabel);
ui->depInfoLabel->setEnabled(false);
ui->depInfosView->setEnabled(false);
ui->depTabPossiblePhases->setEnabled(false);
ui->calculateDependencies->setEnabled(false);
}
void TraceFileTab::tracefileChanged()
{
if (savingChangesToDB == true)
{
// Database has changed due to user action (e.g., saving comments).
// No need to disable the "Save changes to DB" menu.
savingChangesToDB = false;
Q_EMIT statusChanged(QString("Changes saved "));
}
else
{
// External event changed the database file (e.g., the database file
// was overwritten when running a new test).
// The "Save changes to DB" menu must be disabled to avoid saving
// changes to a corrupted or inconsistent file.
Q_EMIT statusChanged(QString("At least one database has changed on disk "));
}
navigator->refreshData();
}
void TraceFileTab::closeEvent(QCloseEvent* event)
{
if (navigator->existChangesToCommit())
{
QMessageBox saveDialog;
saveDialog.setWindowTitle(QFileInfo(traceFilePath.data()).baseName());
saveDialog.setText("The trace file has been modified.");
saveDialog.setInformativeText(
"Do you want to save your changes?<br><b>Unsaved changes will be lost.</b>");
saveDialog.setStandardButtons(QMessageBox::Save | QMessageBox::Discard |
QMessageBox::Cancel);
saveDialog.setDefaultButton(QMessageBox::Save);
saveDialog.setIcon(QMessageBox::Warning);
int returnCode = saveDialog.exec();
switch (returnCode)
{
case QMessageBox::Cancel:
event->ignore();
break;
case QMessageBox::Discard:
event->accept();
break;
case QMessageBox::Save:
commitChangesToDB();
event->accept();
break;
};
}
else
event->accept();
}
traceTime TraceFileTab::getCurrentTraceTime() const
{
return navigator->CurrentTraceTime();
}
void TraceFileTab::navigateToTime(traceTime time)
{
navigator->navigateToTime(time);
}
traceTime TraceFileTab::getZoomLevel() const
{
TracePlot* traceplot = static_cast<TracePlot*>(ui->traceplot);
return traceplot->ZoomLevel();
}
void TraceFileTab::setZoomLevel(traceTime zoomLevel)
{
TracePlot* traceplot = static_cast<TracePlot*>(ui->traceplot);
TraceScroller* tracescroller = static_cast<TraceScroller*>(ui->traceScroller);
traceplot->setZoomLevel(zoomLevel);
tracescroller->tracePlotZoomChanged();
}
std::shared_ptr<AbstractTracePlotLineModel::Node> TraceFileTab::saveTraceSelectorState() const
{
return selectedRowsModel->getClonedRootNode();
}
void TraceFileTab::restoreTraceSelectorState(
std::shared_ptr<AbstractTracePlotLineModel::Node> rootNode)
{
selectedRowsModel->setRootNode(std::move(rootNode));
}
bool TraceFileTab::eventFilter(QObject* object, QEvent* event)
{
if (auto canvas = qobject_cast<QwtPlotCanvas*>(object))
{
if (event->type() == QEvent::MouseButtonDblClick)
{
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
if (mouseEvent->button() != Qt::LeftButton)
return false;
QwtPlot* plot = canvas->plot();
double realTime = plot->invTransform(QwtPlot::xBottom, mouseEvent->x());
// Convert from seconds to picoseconds
traceTime time = realTime * 1000 * 1000 * 1000 * 1000;
navigator->navigateToTime(time);
return true;
}
}
return QWidget::eventFilter(object, event);
}

View File

@@ -40,13 +40,17 @@
#ifndef TRACEFILETAB_H
#define TRACEFILETAB_H
#include "ui_tracefiletab.h"
#include "businessObjects/configmodels.h"
#ifdef EXTENSION_ENABLED
#include "businessObjects/dependencymodels.h"
#endif
#include "businessObjects/traceplotlinemodel.h"
#include "presentation/tracenavigator.h"
#include "presentation/traceplot.h"
#include "presentation/tracescroller.h"
#include "businessObjects/configmodels.h"
#include "businessObjects/dependencymodels.h"
#include <QFileSystemWatcher>
#include <QString>
#include <QTreeWidget>
@@ -57,11 +61,6 @@ class McConfigModel;
class MemSpecModel;
class PythonCaller;
namespace Ui
{
class TraceFileTab;
}
class TraceFileTab : public QWidget
{
Q_OBJECT
@@ -76,11 +75,15 @@ public:
void setUpTraceplotScrollbar();
void setUpCommentView();
void setUpTraceSelector();
void addDisclaimer();
#ifdef EXTENSION_ENABLED
void setUpPossiblePhases();
#endif
void initNavigatorAndItsDependentWidgets();
QString getPathToTraceFile() { return traceFilePath.data(); }
void commitChangesToDB(void);
void commitChangesToDB();
void exportAsVCD();
traceTime getCurrentTraceTime() const;
@@ -116,7 +119,9 @@ private:
SelectedTracePlotLineModel* selectedRowsModel;
TracePlotLineDataSource* tracePlotLineDataSource;
#ifdef EXTENSION_ENABLED
QAbstractItemModel* depInfosView;
#endif
PythonCaller& pythonCaller;
@@ -131,10 +136,12 @@ Q_SIGNALS:
void colorGroupingChanged(ColorGrouping colorgrouping);
private Q_SLOTS:
#ifdef EXTENSION_ENABLED
void on_latencyTreeView_doubleClicked(const QModelIndex& index);
void on_calculateDependencies_clicked();
void on_startLatencyAnalysis_clicked();
void on_startPowerAnalysis_clicked();
#endif
};
#endif // TRACEFILETAB_H

View File

@@ -261,33 +261,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDepInfos">
<attribute name="title">
<string>Dependency Information</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_depInfos">
<item>
<widget class="QTreeView" name="depInfosView">
<property name="uniformRowHeights">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="depTabPossiblePhases">
</widget>
</item>
<item>
<widget class="QPushButton" name="calculateDependencies">
<property name="text">
<string>Calculate Dependencies</string>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="tabComments">
<attribute name="title">
<string>Comments</string>
@@ -317,7 +290,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabLatencyAnalysis">
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Ignored">
@@ -330,7 +302,7 @@
</attribute>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_7">
<layout class="QVBoxLayout" name="latencyLayout">
<item>
<widget class="QPushButton" name="startLatencyAnalysis">
<property name="text">
@@ -366,7 +338,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabPowerAnalysis">
<property name="enabled">
<bool>true</bool>
@@ -390,15 +361,15 @@
<string>Power and Bandwidth Analysis</string>
</attribute>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<widget class="QPushButton" name="startPowerAnalysis">
<property name="text">
<string>Start Analysis</string>
</property>
</widget>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item row="2" column="0">
<layout class="QVBoxLayout" name="powerLayout">
<item>
<widget class="QPushButton" name="startPowerAnalysis">
<property name="text">
<string>Start Analysis</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="powerBox">
<property name="title">
@@ -439,6 +410,43 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tabDepInfos">
<attribute name="title">
<string>Dependency Information</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_depInfos">
<item>
<widget class="QLabel" name="depInfoLabel">
<property name="text">
<string>To display timing dependencies between transaction phases, select the respective phases and press &quot;Calculate Dependencies&quot;. The dependencies can now be displayed in the trace view using the context menu.</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QTreeView" name="depInfosView">
<property name="uniformRowHeights">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QListWidget" name="depTabPossiblePhases"/>
</item>
<item>
<widget class="QPushButton" name="calculateDependencies">
<property name="text">
<string>Calculate Dependencies</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</widget>
</item>