Introduce a gui simulation dialog in TraceAnalyzer

A simulation dialog is added to the TraceAnalyzer that can be used
to directly load a json config, edit it and start a simulation
based on the changes that were made, even without saving again.
The simulation results are opened directly after suceeding.
This commit is contained in:
2021-11-05 09:35:25 +01:00
parent 7d21f3befe
commit 3d0e321075
24 changed files with 1041 additions and 218 deletions

View File

@@ -101,4 +101,17 @@ void from_json(const json &j, XorPair &x)
j.at("SECOND").get_to(x.second);
}
void from_dump(const std::string &dump, AddressMapping &c)
{
json json_addressmapping = json::parse(dump).at("addressmapping");
json_addressmapping.get_to(c);
}
std::string dump(const AddressMapping &c, unsigned int indentation)
{
json json_addressmapping;
json_addressmapping["addressmapping"] = c;
return json_addressmapping.dump(indentation);
}
} // namespace DRAMSysConfiguration

View File

@@ -71,6 +71,9 @@ struct AddressMapping
void to_json(json &j, const AddressMapping &m);
void from_json(const json &j, AddressMapping &m);
void from_dump(const std::string &dump, AddressMapping &c);
std::string dump(const AddressMapping &c, unsigned int indentation = -1);
} // namespace Configuration
#endif // ADDRESSMAPPING_H

View File

@@ -67,6 +67,19 @@ void from_json(const json &j, Configuration &c)
j.at("tracesetup").get_to(c.traceSetup);
}
void from_dump(const std::string &dump, Configuration &c)
{
json json_simulation = json::parse(dump).at("simulation");
json_simulation.get_to(c);
}
std::string dump(const Configuration &c, unsigned int indentation)
{
json json_simulation;
json_simulation["simulation"] = c;
return json_simulation.dump(indentation);
}
Configuration from_path(const std::string &path, const std::string &resourceDirectory)
{
Configuration::resourceDirectory = resourceDirectory;

View File

@@ -78,6 +78,9 @@ struct Configuration
void to_json(json &j, const Configuration &p);
void from_json(const json &j, Configuration &p);
void from_dump(const std::string &dump, Configuration &c);
std::string dump(const Configuration &c, unsigned int indentation = -1);
Configuration from_path(const std::string &path, const std::string &resourceDirectory = DRAMSysResourceDirectory);
} // namespace DRAMSysConfiguration

View File

@@ -52,7 +52,13 @@ void to_json(json &j, const McConfig &c)
{"PowerDownPolicy", c.powerDownPolicy},
{"Arbiter", c.arbiter},
{"MaxActiveTransactions", c.maxActiveTransactions},
{"RefreshManagment", c.refreshManagement}};
{"RefreshManagment", c.refreshManagement},
{"ArbitrationDelayFw", c.arbitrationDelayFw},
{"ArbitrationDelayBw", c.arbitrationDelayBw},
{"ThinkDelayFw", c.thinkDelayFw},
{"ThinkDelayBw", c.thinkDelayBw},
{"PhyDelayFw", c.phyDelayFw},
{"PhyDelayBw", c.phyDelayBw}};
remove_null_values(j);
}
@@ -100,6 +106,24 @@ void from_json(const json &j, McConfig &c)
if (j_mcconfig.contains("RefreshManagment"))
j_mcconfig.at("RefreshManagment").get_to(c.refreshManagement);
if (j_mcconfig.contains("ArbitrationDelayFw"))
j_mcconfig.at("ArbitrationDelayFw").get_to(c.arbitrationDelayFw);
if (j_mcconfig.contains("ArbitrationDelayBw"))
j_mcconfig.at("ArbitrationDelayBw").get_to(c.arbitrationDelayBw);
if (j_mcconfig.contains("ThinkDelayFw"))
j_mcconfig.at("ThinkDelayFw").get_to(c.thinkDelayFw);
if (j_mcconfig.contains("ThinkDelayBw"))
j_mcconfig.at("ThinkDelayBw").get_to(c.thinkDelayBw);
if (j_mcconfig.contains("PhyDelayFw"))
j_mcconfig.at("PhyDelayFw").get_to(c.phyDelayFw);
if (j_mcconfig.contains("PhyDelayBw"))
j_mcconfig.at("PhyDelayBw").get_to(c.phyDelayBw);
invalidateEnum(c.pagePolicy);
invalidateEnum(c.scheduler);
invalidateEnum(c.schedulerBuffer);
@@ -111,11 +135,17 @@ void from_json(const json &j, McConfig &c)
invalidateEnum(c.arbiter);
}
std::string dump(const McConfig &c)
void from_dump(const std::string &dump, McConfig &c)
{
json json_mcconfig = json::parse(dump).at("mcconfig");
json_mcconfig.get_to(c);
}
std::string dump(const McConfig &c, unsigned int indentation)
{
json json_mcconfig;
json_mcconfig["mcconfig"] = c;
return json_mcconfig.dump();
return json_mcconfig.dump(indentation);
}
} // namespace DRAMSysConfiguration

View File

@@ -119,14 +119,20 @@ enum class RefreshPolicy
PerBank,
Per2Bank,
SameBank,
Rankwise,
Bankwise,
Groupwise,
Invalid = -1
};
NLOHMANN_JSON_SERIALIZE_ENUM(RefreshPolicy, {{RefreshPolicy::Invalid, nullptr},
{RefreshPolicy::NoRefresh, "NoRefresh"},
{RefreshPolicy::AllBank, "AllBank"},
{RefreshPolicy::PerBank, "PerBank"},
{RefreshPolicy::Per2Bank, "Per2Bank"},
{RefreshPolicy::SameBank, "SameBank"}})
{RefreshPolicy::Rankwise, "Rankwise"},
{RefreshPolicy::Bankwise, "Bankwise"},
{RefreshPolicy::Groupwise, "Groupwise"}})
enum class PowerDownPolicy
{
@@ -167,12 +173,19 @@ struct McConfig
Optional<Arbiter> arbiter;
Optional<unsigned int> maxActiveTransactions;
Optional<bool> refreshManagement;
Optional<unsigned int> arbitrationDelayFw;
Optional<unsigned int> arbitrationDelayBw;
Optional<unsigned int> thinkDelayFw;
Optional<unsigned int> thinkDelayBw;
Optional<unsigned int> phyDelayFw;
Optional<unsigned int> phyDelayBw;
};
void to_json(json &j, const McConfig &c);
void from_json(const json &j, McConfig &c);
std::string dump(const McConfig &c);
void from_dump(const std::string &dump, McConfig &c);
std::string dump(const McConfig &c, unsigned int indentation = -1);
} // namespace Configuration

View File

@@ -110,4 +110,17 @@ void from_json(const json &j, SimConfig &c)
invalidateEnum(c.storeMode);
}
void from_dump(const std::string &dump, SimConfig &c)
{
json json_simconfig = json::parse(dump).at("simconfig");
json_simconfig.get_to(c);
}
std::string dump(const SimConfig &c, unsigned int indentation)
{
json json_simconfig;
json_simconfig["simconfig"] = c;
return json_simconfig.dump(indentation);
}
} // namespace DRAMSysConfiguration

View File

@@ -92,6 +92,9 @@ struct SimConfig
void to_json(json &j, const SimConfig &c);
void from_json(const json &j, SimConfig &c);
void from_dump(const std::string &dump, SimConfig &c);
std::string dump(const SimConfig &c, unsigned int indentation = -1);
} // namespace Configuration
#endif

View File

@@ -105,4 +105,17 @@ void from_json(const json &j, PowerInfo &c)
}
}
void from_dump(const std::string &dump, ThermalConfig &c)
{
json json_thermalconfig = json::parse(dump).at("thermalconfig");
json_thermalconfig.get_to(c);
}
std::string dump(const ThermalConfig &c, unsigned int indentation)
{
json json_thermalconfig;
json_thermalconfig["thermalconfig"] = c;
return json_thermalconfig.dump(indentation);
}
} // namespace DRAMSysConfiguration

View File

@@ -112,6 +112,9 @@ struct ThermalConfig
void to_json(json &j, const ThermalConfig &c);
void from_json(const json &j, ThermalConfig &c);
void from_dump(const std::string &dump, ThermalConfig &c);
std::string dump(const ThermalConfig &c, unsigned int indentation = -1);
} // namespace Configuration
#endif // THERMALCONFIG_H

View File

@@ -136,4 +136,17 @@ void from_json(const json &j, TraceSetup &c)
}
}
void from_dump(const std::string &dump, TraceSetup &c)
{
json json_tracesetup = json::parse(dump).at("tracesetup");
json_tracesetup.get_to(c);
}
std::string dump(const TraceSetup &c, unsigned int indentation)
{
json json_tracesetup;
json_tracesetup["tracesetup"] = c;
return json_tracesetup.dump(indentation);
}
} // namespace DRAMSysConfiguration

View File

@@ -109,6 +109,9 @@ struct TraceSetup
void to_json(json &j, const TraceSetup &c);
void from_json(const json &j, TraceSetup &c);
void from_dump(const std::string &dump, TraceSetup &c);
std::string dump(const TraceSetup &c, unsigned int indentation = -1);
} // namespace Configuration
#endif

View File

@@ -62,11 +62,17 @@ void from_json(const json &j, MemSpec &c)
j_memspecs.at("mempowerspec").get_to(c.memPowerSpec);
}
std::string dump(const MemSpec &c)
void from_dump(const std::string &dump, MemSpec &c)
{
json json_memspec = json::parse(dump).at("memspec");
json_memspec.get_to(c);
}
std::string dump(const MemSpec &c, unsigned int indentation)
{
json json_memspec;
json_memspec["memspec"] = c;
return json_memspec.dump();
return json_memspec.dump(indentation);
}
} // namespace Configuration

View File

@@ -61,7 +61,8 @@ struct MemSpec
void to_json(json &j, const MemSpec &c);
void from_json(const json &j, MemSpec &c);
std::string dump(const MemSpec &c);
void from_dump(const std::string &dump, MemSpec &c);
std::string dump(const MemSpec &c, unsigned int indentation = -1);
} // namespace Configuration

View File

@@ -75,6 +75,16 @@ public:
{
this->second = false;
}
/**
* This methods only purpose is to make a optional type
* valid so that it can be written to by reference.
*/
T &setByReference()
{
this->second = true;
return this->first;
}
};
template <typename T>

View File

@@ -77,212 +77,6 @@ enum sc_time_unit string2TimeUnit(const std::string &s)
}
}
// void Configuration::setParameter(const std::string &name, const nlohmann::json &value)
// {
// MCConfig
// if (name == "PagePolicy")
// {
// if (value == "Open")
// pagePolicy = PagePolicy::Open;
// else if (value == "Closed")
// pagePolicy = PagePolicy::Closed;
// else if (value == "OpenAdaptive")
// pagePolicy = PagePolicy::OpenAdaptive;
// else if (value == "ClosedAdaptive")
// pagePolicy = PagePolicy::ClosedAdaptive;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported page policy!");
// }
// else if (name == "Scheduler")
// {
// if (value == "Fifo")
// scheduler = Scheduler::Fifo;
// else if (value == "FrFcfs")
// scheduler = Scheduler::FrFcfs;
// else if (value == "FrFcfsGrp")
// scheduler = Scheduler::FrFcfsGrp;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported scheduler!");
// }
// else if (name == "SchedulerBuffer")
// {
// if (value == "Bankwise")
// schedulerBuffer = SchedulerBuffer::Bankwise;
// else if (value == "ReadWrite")
// schedulerBuffer = SchedulerBuffer::ReadWrite;
// else if (value == "Shared")
// schedulerBuffer = SchedulerBuffer::Shared;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported scheduler buffer!");
// }
// else if (name == "RequestBufferSize")
// {
// requestBufferSize = value;
// if (requestBufferSize == 0)
// SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!");
// }
// else if (name == "CmdMux")
// {
// if (value == "Oldest")
// cmdMux = CmdMux::Oldest;
// else if (value == "Strict")
// cmdMux = CmdMux::Strict;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported cmd mux!");
// }
// else if (name == "RespQueue")
// {
// if (value == "Fifo")
// respQueue = RespQueue::Fifo;
// else if (value == "Reorder")
// respQueue = RespQueue::Reorder;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported response queue!");
// }
// else if (name == "Arbiter")
// {
// if (value == "Simple")
// arbiter = Arbiter::Simple;
// else if (value == "Fifo")
// arbiter = Arbiter::Fifo;
// else if (value == "Reorder")
// arbiter = Arbiter::Reorder;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported arbiter!");
// }
// else if (name == "RefreshPolicy")
// {
// if (value == "NoRefresh")
// refreshPolicy = RefreshPolicy::NoRefresh;
// else if (value == "AllBank" || value == "Rankwise")
// refreshPolicy = RefreshPolicy::AllBank;
// else if (value == "PerBank" || value == "Bankwise")
// refreshPolicy = RefreshPolicy::PerBank;
// else if (value == "SameBank" || value == "Groupwise")
// refreshPolicy = RefreshPolicy::SameBank;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported refresh policy!");
// }
// else if (name == "RefreshMaxPostponed")
// refreshMaxPostponed = value;
// else if (name == "RefreshMaxPulledin")
// refreshMaxPulledin = value;
// else if (name == "PowerDownPolicy")
// {
// if (value == "NoPowerDown")
// powerDownPolicy = PowerDownPolicy::NoPowerDown;
// else if (value == "Staggered")
// powerDownPolicy = PowerDownPolicy::Staggered;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported power down policy!");
// }
// else if (name == "RefreshManagement")
// refreshManagement = value;
// else if (name == "PowerDownTimeout")
// powerDownTimeout = value;
// else if (name == "MaxActiveTransactions")
// maxActiveTransactions = value;
// else if (name == "ArbitrationDelayFw")
// arbitrationDelayFw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// else if (name == "ArbitrationDelayBw")
// arbitrationDelayBw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// else if (name == "ThinkDelayFw")
// thinkDelayFw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// else if (name == "ThinkDelayBw")
// thinkDelayBw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// else if (name == "PhyDelayFw")
// phyDelayFw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// else if (name == "PhyDelayBw")
// phyDelayBw = std::round(sc_time(value, SC_NS) / memSpec->tCK) * memSpec->tCK;
// SimConfig------------------------------------------------
// else if (name == "SimulationName")
// simulationName = value;
// else if (name == "DatabaseRecording")
// databaseRecording = value;
// else if (name == "PowerAnalysis")
// powerAnalysis = value;
// else if (name == "EnableWindowing")
// enableWindowing = value;
// else if (name == "WindowSize")
// {
// windowSize = value;
// if (windowSize == 0)
// SC_REPORT_FATAL("Configuration", "Minimum window size is 1");
// }
// else if (name == "Debug")
// debug = value;
// else if (name == "ThermalSimulation")
// thermalSimulation = value;
// else if (name == "SimulationProgressBar")
// simulationProgressBar = value;
// else if (name == "AddressOffset")
// addressOffset = value;
// else if (name == "UseMalloc")
// useMalloc = value;
// else if (name == "CheckTLM2Protocol")
// checkTLM2Protocol = value;
// else if (name == "ECCControllerMode")
// {
// if (value == "Disabled")
// eccMode = ECCMode::Disabled;
// else if (value == "Hamming")
// eccMode = ECCMode::Hamming;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported ECC mode!");
// }
// Specification for ErrorChipSeed, ErrorCSVFile path and StoreMode
// else if (name == "ErrorChipSeed")
// errorChipSeed = value;
// else if (name == "ErrorCSVFile")
// errorCSVFile = value;
// else if (name == "StoreMode")
// {
// if (value == "NoStorage")
// storeMode = StoreMode::NoStorage;
// else if (value == "Store")
// storeMode = StoreMode::Store;
// else if (value == "ErrorModel")
// storeMode = StoreMode::ErrorModel;
// else
// SC_REPORT_FATAL("Configuration", "Unsupported store mode!");
// }
//
// Temperature Simulation related
// else if (name == "TemperatureScale")
// {
// if (value != "Celsius" && value != "Fahrenheit" && value != "Kelvin")
// SC_REPORT_FATAL("Configuration",
// ("Invalid value for parameter " + name + ".").c_str());
// temperatureSim.temperatureScale = value;
// }
// else if (name == "StaticTemperatureDefaultValue")
// temperatureSim.staticTemperatureDefaultValue = value;
// else if (name == "ThermalSimPeriod")
// temperatureSim.thermalSimPeriod = value;
// else if (name == "ThermalSimUnit")
// temperatureSim.thermalSimUnit = string2TimeUnit(value);
// else if (name == "PowerInfoFile")
// {
// temperatureSim.powerInfoFile = value;
// temperatureSim.parsePowerInfoFile();
// }
// else if (name == "IceServerIp")
// temperatureSim.iceServerIp = value;
// else if (name == "IceServerPort")
// temperatureSim.iceServerPort = value;
// else if (name == "SimPeriodAdjustFactor")
// temperatureSim.simPeriodAdjustFactor = value;
// else if (name == "NPowStableCyclesToIncreasePeriod")
// temperatureSim.nPowStableCyclesToIncreasePeriod = value;
// else if (name == "GenerateTemperatureMap")
// temperatureSim.generateTemperatureMap = value;
// else if (name == "GeneratePowerMap")
// temperatureSim.generatePowerMap = value;
// else
// SC_REPORT_FATAL("Configuration",
// ("Parameter " + name + " not defined in Configuration").c_str());
// }
// Changes the number of bytes depeding on the ECC Controller. This function is needed for modules which get data directly or indirectly from the ECC Controller
unsigned int Configuration::adjustNumBytesAfterECC(unsigned nBytes) const
{
@@ -343,6 +137,8 @@ void Configuration::loadSimConfig(Configuration &config, const DRAMSysConfigurat
if (simConfig.windowSize.isValid())
config.windowSize = simConfig.windowSize.getValue();
if (config.windowSize == 0)
SC_REPORT_FATAL("Configuration", "Minimum window size is 1");
if (simConfig.errorCsvFile.isValid())
config.errorCSVFile = simConfig.errorCsvFile.getValue();
@@ -451,6 +247,9 @@ void Configuration::loadMCConfig(Configuration &config, const DRAMSysConfigurati
if (mcConfig.requestBufferSize.isValid())
config.requestBufferSize = mcConfig.requestBufferSize.getValue();
if (config.requestBufferSize == 0)
SC_REPORT_FATAL("Configuration", "Minimum request buffer size is 1!");
if (mcConfig.cmdMux.isValid())
config.cmdMux = [=] {
auto cmdMux = mcConfig.cmdMux.getValue();
@@ -477,13 +276,13 @@ void Configuration::loadMCConfig(Configuration &config, const DRAMSysConfigurati
if (policy == DRAMSysConfiguration::RefreshPolicy::NoRefresh)
return RefreshPolicy::NoRefresh;
else if (policy == DRAMSysConfiguration::RefreshPolicy::AllBank)
else if (policy == DRAMSysConfiguration::RefreshPolicy::AllBank || policy == DRAMSysConfiguration::RefreshPolicy::Rankwise)
return RefreshPolicy::AllBank;
else if (policy == DRAMSysConfiguration::RefreshPolicy::PerBank)
else if (policy == DRAMSysConfiguration::RefreshPolicy::PerBank || policy == DRAMSysConfiguration::RefreshPolicy::Bankwise)
return RefreshPolicy::PerBank;
else if (policy == DRAMSysConfiguration::RefreshPolicy::Per2Bank)
return RefreshPolicy::Per2Bank;
else
else // if (policy == DRAMSysConfiguration::RefreshPolicy::SameBank || policy == DRAMSysConfiguration::RefreshPolicy::Groupwise)
return RefreshPolicy::SameBank;
}();
@@ -520,6 +319,36 @@ void Configuration::loadMCConfig(Configuration &config, const DRAMSysConfigurati
if (mcConfig.refreshManagement.isValid())
config.refreshManagement = mcConfig.refreshManagement.getValue();
if (mcConfig.arbitrationDelayFw.isValid())
{
config.arbitrationDelayFw = std::round(sc_time(mcConfig.arbitrationDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
if (mcConfig.arbitrationDelayBw.isValid())
{
config.arbitrationDelayBw = std::round(sc_time(mcConfig.arbitrationDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
if (mcConfig.thinkDelayFw.isValid())
{
config.thinkDelayFw = std::round(sc_time(mcConfig.thinkDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
if (mcConfig.thinkDelayBw.isValid())
{
config.thinkDelayBw = std::round(sc_time(mcConfig.thinkDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
if (mcConfig.phyDelayFw.isValid())
{
config.phyDelayFw = std::round(sc_time(mcConfig.phyDelayFw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
if (mcConfig.phyDelayBw.isValid())
{
config.phyDelayBw = std::round(sc_time(mcConfig.phyDelayBw.getValue(), SC_NS) / config.memSpec->tCK) * config.memSpec->tCK;
}
}
void Configuration::loadMemSpec(Configuration &config, const DRAMSysConfiguration::MemSpec &memSpecConfig)

View File

@@ -77,7 +77,8 @@ DRAMSys::DRAMSys(const sc_core::sc_module_name &name,
logo();
// Load config and initialize modules
Configuration::getInstance().loadMemSpec(Configuration::getInstance(), config.memSpec);
// Important: The memSpec needs to be the first configuration to be loaded!
Configuration::loadMemSpec(Configuration::getInstance(), config.memSpec);
Configuration::loadMCConfig(Configuration::getInstance(), config.mcConfig);
Configuration::loadSimConfig(Configuration::getInstance(), config.simConfig);

View File

@@ -100,6 +100,7 @@ add_executable(TraceAnalyzer
presentation/traceselector.cpp
businessObjects/configmodels.cpp
businessObjects/commentmodel.cpp
simulationdialog.cpp
selectmetrics.ui
preferences.ui
@@ -108,6 +109,7 @@ add_executable(TraceAnalyzer
tracefiletab.ui
queryeditor.ui
traceanalyzer.ui
simulationdialog.ui
scripts/memUtil.py
scripts/metrics.py
@@ -131,4 +133,5 @@ target_link_libraries(TraceAnalyzer
PRIVATE ${QWT_LIBRARY}
PRIVATE Qt5::Widgets
PRIVATE Qt5::Sql
PRIVATE DRAMSysConfiguration
)

View File

@@ -0,0 +1,377 @@
/*
* Copyright (c) 2021s, 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 <QDateTime>
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QMessageBox>
#include <QRegularExpression>
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_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);
}
}
});
simulatorProcess->setWorkingDirectory(ui->outputDirLineEdit->text());
simulatorProcess->start(ui->dramSysPath->text(), QStringList(temporaryConfigurationFile.fileName()));
}
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;
}
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;
Optional<ThermalConfig> thermalConfig;
Optional<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.setByReference());
if (!ui->traceSetupTextEdit->toPlainText().toStdString().empty())
from_dump(ui->traceSetupTextEdit->toPlainText().toStdString(), traceSetup.setByReference());
}
catch (const std::exception &e)
{
qWarning() << "Error while parsing json:" << e.what();
return;
}
configuration = DRAMSysConfiguration::Configuration{addressMapping, mcConfig, memSpec, simConfig,
simulationId, thermalConfig, 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 (configuration.thermalConfig.isValid())
{
std::string dump = DRAMSysConfiguration::dump(configuration.thermalConfig.getValue(), 4);
ui->thermalConfigTextEdit->setText(dump.c_str());
}
}
void SimulationDialog::loadTraceSetup()
{
ui->traceSetupTextEdit->clear();
if (configuration.traceSetup.isValid())
{
std::string dump = DRAMSysConfiguration::dump(configuration.traceSetup.getValue(), 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());
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (c) 2021s, 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
*/
#ifndef SIMULATIONDIALOG_H
#define SIMULATIONDIALOG_H
#include "ui_simulationdialog.h"
#include <Configuration.h>
#include <QFileInfo>
#include <QPointer>
#include <QProcess>
#include <QSyntaxHighlighter>
#include <QTemporaryFile>
#include <QWidget>
namespace Ui
{
class SimulationDialog;
}
class SimulationDialog : public QWidget
{
Q_OBJECT
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_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 loadThermalConfig();
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;
DRAMSysConfiguration::Configuration configuration;
QPointer<QProcess> simulatorProcess;
Ui::SimulationDialog *ui;
};
#endif

View File

@@ -0,0 +1,345 @@
<?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>884</width>
<height>522</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="2" column="2">
<widget class="QPushButton" name="browseConfigButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="jsonPath">
<property name="placeholderText">
<string>Path to Json configuration...</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="dramSysPath">
<property name="placeholderText">
<string>Path to DRAMSys...</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="0" column="2">
<widget class="QPushButton" name="browseDramSysButton">
<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="1" column="1">
<widget class="QLineEdit" name="outputDirLineEdit">
<property name="placeholderText">
<string>Path to output directory...</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QPushButton" name="browseOutputButton">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="outputDirLabel">
<property name="text">
<string>Output 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>
<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

@@ -37,8 +37,10 @@
*/
#include "traceanalyzer.h"
#include "simulationdialog.h"
#include "tracefiletab.h"
#include "ui_traceanalyzer.h"
#include <QCloseEvent>
#include <QDateTime>
#include <QFileDialog>
@@ -281,3 +283,13 @@ 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

@@ -97,6 +97,7 @@ 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

@@ -78,7 +78,14 @@
</property>
<addaction name="actionAbout"/>
</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"/>
@@ -225,6 +232,14 @@
<string>Save &amp;as...</string>
</property>
</action>
<action name="actionSimulate">
<property name="icon">
<iconset theme="system-run"/>
</property>
<property name="text">
<string>&amp;Simulate...</string>
</property>
</action>
</widget>
<resources/>
<connections>