Added extension mechanism and ported DDR5, LPDDR5, HBM3, TraceAnalyzer
This commit is contained in:
409
extensions/apps/traceAnalyzer/simulationdialog.cpp
Normal file
409
extensions/apps/traceAnalyzer/simulationdialog.cpp
Normal file
@@ -0,0 +1,409 @@
|
||||
/*
|
||||
* Copyright (c) 2021, Technische Universität Kaiserslautern
|
||||
* 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 "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 = DRAMSysConfiguration::dump(configuration, 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 DRAMSysConfiguration;
|
||||
|
||||
AddressMapping addressMapping;
|
||||
McConfig mcConfig;
|
||||
MemSpec memSpec;
|
||||
SimConfig simConfig;
|
||||
std::string simulationId;
|
||||
ThermalConfig thermalConfig;
|
||||
TraceSetup traceSetup;
|
||||
|
||||
simulationId = ui->simulationIdLineEdit->text().toStdString();
|
||||
|
||||
try
|
||||
{
|
||||
from_dump(ui->addressMappingTextEdit->toPlainText().toStdString(), addressMapping);
|
||||
from_dump(ui->mcConfigTextEdit->toPlainText().toStdString(), mcConfig);
|
||||
from_dump(ui->memSpecTextEdit->toPlainText().toStdString(), memSpec);
|
||||
from_dump(ui->simConfigTextEdit->toPlainText().toStdString(), simConfig);
|
||||
|
||||
if (!ui->thermalConfigTextEdit->toPlainText().toStdString().empty())
|
||||
from_dump(ui->thermalConfigTextEdit->toPlainText().toStdString(), thermalConfig);
|
||||
|
||||
if (!ui->traceSetupTextEdit->toPlainText().toStdString().empty())
|
||||
from_dump(ui->traceSetupTextEdit->toPlainText().toStdString(), traceSetup);
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
qWarning() << "Error while parsing json:" << e.what();
|
||||
return;
|
||||
}
|
||||
|
||||
configuration = DRAMSysConfiguration::Configuration{addressMapping,
|
||||
mcConfig,
|
||||
memSpec,
|
||||
simConfig,
|
||||
simulationId,
|
||||
std::make_optional<ThermalConfig>(std::move(thermalConfig)),
|
||||
std::make_optional<TraceSetup>(std::move(traceSetup))};
|
||||
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
void SimulationDialog::loadConfigurationFromPath()
|
||||
{
|
||||
QFileInfo fileInfo(ui->jsonPath->text());
|
||||
|
||||
if (!fileInfo.isFile())
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
configuration = DRAMSysConfiguration::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();
|
||||
loadThermalConfig();
|
||||
loadTraceSetup();
|
||||
loadPreview();
|
||||
}
|
||||
|
||||
void SimulationDialog::loadSimConfig()
|
||||
{
|
||||
ui->simConfigTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSysConfiguration::dump(configuration.simConfig, 4);
|
||||
ui->simConfigTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
void SimulationDialog::loadMcConfig()
|
||||
{
|
||||
ui->mcConfigTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSysConfiguration::dump(configuration.mcConfig, 4);
|
||||
ui->mcConfigTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
void SimulationDialog::loadMemSpec()
|
||||
{
|
||||
ui->memSpecTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSysConfiguration::dump(configuration.memSpec, 4);
|
||||
ui->memSpecTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
void SimulationDialog::loadAddressMapping()
|
||||
{
|
||||
ui->addressMappingTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSysConfiguration::dump(configuration.addressMapping, 4);
|
||||
ui->addressMappingTextEdit->setText(dump.c_str());
|
||||
}
|
||||
|
||||
void SimulationDialog::loadThermalConfig()
|
||||
{
|
||||
ui->thermalConfigTextEdit->clear();
|
||||
|
||||
if (const auto &thermalConfig = configuration.thermalConfig)
|
||||
{
|
||||
std::string dump = DRAMSysConfiguration::dump(*thermalConfig, 4);
|
||||
ui->thermalConfigTextEdit->setText(dump.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SimulationDialog::loadTraceSetup()
|
||||
{
|
||||
ui->traceSetupTextEdit->clear();
|
||||
|
||||
if (const auto &traceSetup = configuration.traceSetup)
|
||||
{
|
||||
std::string dump = DRAMSysConfiguration::dump(*traceSetup, 4);
|
||||
ui->traceSetupTextEdit->setText(dump.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void SimulationDialog::loadPreview()
|
||||
{
|
||||
ui->previewTextEdit->clear();
|
||||
|
||||
std::string dump = DRAMSysConfiguration::dump(configuration, 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());
|
||||
}
|
||||
Reference in New Issue
Block a user