/* * 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 #include #include #include #include #include #include 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::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(std::move(thermalConfig)), std::make_optional(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()); }