diff --git a/DRAMSys/library/src/common/TlmRecorder.cpp b/DRAMSys/library/src/common/TlmRecorder.cpp index 100411cb..15a54d35 100644 --- a/DRAMSys/library/src/common/TlmRecorder.cpp +++ b/DRAMSys/library/src/common/TlmRecorder.cpp @@ -342,8 +342,15 @@ void TlmRecorder::insertGeneralInfo() sqlite3_bind_int(insertGeneralInfoStatement, 5, static_cast(Configuration::getInstance().memSpec->numberOfBanks)); sqlite3_bind_int(insertGeneralInfoStatement, 6, static_cast(Configuration::getInstance().memSpec->tCK.value())); sqlite3_bind_text(insertGeneralInfoStatement, 7, "PS", 2, nullptr); - sqlite3_bind_text(insertGeneralInfoStatement, 8, mcconfig.c_str(), static_cast(mcconfig.length()), nullptr); - sqlite3_bind_text(insertGeneralInfoStatement, 9, memspec.c_str(), static_cast(memspec.length()), nullptr); + + std::fstream mcconfig_stream, memspec_stream; + mcconfig_stream.open(mcconfig, std::ios::in); + memspec_stream.open(memspec, std::ios::in); + std::string mcconfig_dump((std::istreambuf_iterator(mcconfig_stream)), (std::istreambuf_iterator())); + std::string memspec_dump((std::istreambuf_iterator(memspec_stream)), (std::istreambuf_iterator())); + + sqlite3_bind_text(insertGeneralInfoStatement, 8, mcconfig_dump.c_str(), static_cast(mcconfig_dump.length()), nullptr); + sqlite3_bind_text(insertGeneralInfoStatement, 9, memspec_dump.c_str(), static_cast(memspec_dump.length()), nullptr); sqlite3_bind_text(insertGeneralInfoStatement, 10, traces.c_str(), static_cast(traces.length()), nullptr); if (!Configuration::getInstance().enableWindowing) sqlite3_bind_int64(insertGeneralInfoStatement, 11, 0); diff --git a/DRAMSys/traceAnalyzer/CMakeLists.txt b/DRAMSys/traceAnalyzer/CMakeLists.txt index f182b186..ae70b48c 100644 --- a/DRAMSys/traceAnalyzer/CMakeLists.txt +++ b/DRAMSys/traceAnalyzer/CMakeLists.txt @@ -96,6 +96,7 @@ add_executable(TraceAnalyzer presentation/util/traceplotlinecache.cpp presentation/util/customlabelscaledraw.cpp presentation/traceselector.cpp + businessObjects/configmodels.cpp selectmetrics.ui preferences.ui diff --git a/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp new file mode 100644 index 00000000..b3d4400f --- /dev/null +++ b/DRAMSys/traceAnalyzer/businessObjects/configmodels.cpp @@ -0,0 +1,273 @@ +/* + * 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 "configmodels.h" + +#include +#include + +McConfigModel::McConfigModel(const TraceDB &traceFile, QObject *parent) : QAbstractTableModel(parent) +{ + QSqlDatabase db = traceFile.getDatabase(); + QString query = "SELECT MCconfig FROM GeneralInfo"; + QSqlQuery sqlQuery = db.exec(query); + + // The whole configuration is stored in a single cell. + sqlQuery.next(); + QString mcConfigJson = sqlQuery.value(0).toString(); + + parseJson(mcConfigJson); +} + +void McConfigModel::parseJson(const QString &jsonString) +{ + QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); + QJsonObject mcConfigJson = jsonDocument.object()["mcconfig"].toObject(); + + for (auto key : mcConfigJson.keys()) + { + QJsonValue currentValue = mcConfigJson.value(key); + + if (currentValue.isDouble()) + { + entries.push_back(std::make_pair(key, QString::number(currentValue.toDouble()))); + } + else if (currentValue.isString()) + { + entries.push_back(std::make_pair(key, currentValue.toString())); + } + } +} + +int McConfigModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return entries.size(); +} + +int McConfigModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 2; +} + +QVariant McConfigModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole) + return QVariant(); + + auto entry = entries.at(index.row()); + + if (index.column() == 0) + return entry.first; + else if (index.column() == 1) + return entry.second; + + return QVariant(); +} + +QVariant McConfigModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch (section) { + case 0: + return "Field"; + case 1: + return "Value"; + default: + break; + } + } + + return QVariant(); +} + +MemSpecModel::MemSpecModel(const TraceDB &traceFile, QObject *parent) : QAbstractItemModel(parent) +{ + QSqlDatabase db = traceFile.getDatabase(); + QString query = "SELECT Memspec FROM GeneralInfo"; + QSqlQuery sqlQuery = db.exec(query); + + // The whole configuration is stored in a single cell. + sqlQuery.next(); + QString memSpecJson = sqlQuery.value(0).toString(); + + parseJson(memSpecJson); +} + +int MemSpecModel::Node::getRow() const +{ + if (!parent) + return 0; + + const auto &siblings = parent->children; + const auto siblingsIt = std::find_if(siblings.begin(), siblings.end(), [this](const std::unique_ptr &node){ + return node.get() == this; + }); + + Q_ASSERT(siblingsIt != siblings.end()); + + return std::distance(siblings.begin(), siblingsIt); +} + +void MemSpecModel::parseJson(const QString &jsonString) +{ + QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonString.toUtf8()); + QJsonObject memSpecJson = jsonDocument.object()["memspec"].toObject(); + + std::function &)> addNodes; + addNodes = [&addNodes](const QJsonObject &obj, std::unique_ptr &parentNode) + { + for (auto key : obj.keys()) + { + QJsonValue currentValue = obj.value(key); + + QString value; + if (currentValue.isDouble()) + { + value = QString::number(currentValue.toDouble()); + } + else if (currentValue.isString()) + { + value = currentValue.toString(); + } + + std::unique_ptr node = std::unique_ptr(new Node(std::make_pair(key, value), parentNode.get())); + addNodes(obj[key].toObject(), node); + + parentNode->children.push_back(std::move(node)); + } + }; + + addNodes(memSpecJson, rootNode); +} + +int MemSpecModel::rowCount(const QModelIndex &parent) const +{ + if (parent.column() > 0) + return 0; + + const Node *parentNode; + + if (!parent.isValid()) + parentNode = rootNode.get(); + else + parentNode = static_cast(parent.internalPointer()); + + return parentNode->childCount(); +} + +int MemSpecModel::columnCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return 2; +} + +QVariant MemSpecModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + if (role != Qt::DisplayRole && role != Qt::ToolTipRole) + return QVariant(); + + auto *node = static_cast(index.internalPointer()); + + if (index.column() == 0) + return QVariant(node->data.first); + else + return QVariant(node->data.second); +} + +QVariant MemSpecModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (orientation == Qt::Horizontal) + { + switch (section) { + case 0: + return "Field"; + case 1: + return "Value"; + default: + break; + } + } + + return QVariant(); +} + +QModelIndex MemSpecModel::index(int row, int column, const QModelIndex &parent) const +{ + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + const Node *parentNode; + + if (!parent.isValid()) + parentNode = rootNode.get(); + else + parentNode = static_cast(parent.internalPointer()); + + const Node *node = parentNode->children[row].get(); + + return createIndex(row, column, const_cast(node)); +} + +QModelIndex MemSpecModel::parent(const QModelIndex &index) const +{ + if (!index.isValid()) + return QModelIndex(); + + const Node *childNode = static_cast(index.internalPointer()); + const Node *parentNode = childNode->parent; + + if (!parentNode) + return QModelIndex(); + + return createIndex(parentNode->getRow(), 0, const_cast(parentNode)); +} diff --git a/DRAMSys/traceAnalyzer/businessObjects/configmodels.h b/DRAMSys/traceAnalyzer/businessObjects/configmodels.h new file mode 100644 index 00000000..2548ab39 --- /dev/null +++ b/DRAMSys/traceAnalyzer/businessObjects/configmodels.h @@ -0,0 +1,119 @@ +/* + * 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 + */ + +#ifndef CONFIGMODELS_H +#define CONFIGMODELS_H + +#include "../data/tracedb.h" + +#include +#include +#include + +class McConfigModel : public QAbstractTableModel +{ + Q_OBJECT + +public: + explicit McConfigModel(const TraceDB &traceFile, QObject *parent = nullptr); + ~McConfigModel() {} + +protected: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + +private: + /** + * Parses the json file and adds json entries to the entries vector. + * In case of failure, nothing is added and therefore the model + * will stay empty. + */ + void parseJson(const QString &jsonString); + + std::vector> entries; +}; + +class MemSpecModel : public QAbstractItemModel +{ + Q_OBJECT + +public: + explicit MemSpecModel(const TraceDB &traceFile, QObject *parent = nullptr); + ~MemSpecModel() {} + +protected: + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + int columnCount(const QModelIndex &parent) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; + + QModelIndex index(int row, int column, const QModelIndex &parent) const override; + QModelIndex parent(const QModelIndex &index) const override; + +private: + /** + * Parses the json file and adds json entries to the entries vector. + * In case of failure, nothing is added and therefore the model + * will stay empty. + */ + void parseJson(const QString &jsonString); + + struct Node + { + using NodeData = std::pair; + + Node() {} + Node(NodeData data, const Node *parent) : data(data), parent(parent) {} + + /** + * Gets the row relative to its parent. + */ + int getRow() const; + int childCount() const { return children.size(); } + + NodeData data; + + const Node *parent = nullptr; + std::vector> children; + }; + + std::unique_ptr rootNode = std::unique_ptr(new Node); +}; + +#endif // CONFIGMODELS_H diff --git a/DRAMSys/traceAnalyzer/scripts/memUtil.py b/DRAMSys/traceAnalyzer/scripts/memUtil.py index 96b0bc54..69885ec0 100755 --- a/DRAMSys/traceAnalyzer/scripts/memUtil.py +++ b/DRAMSys/traceAnalyzer/scripts/memUtil.py @@ -17,7 +17,7 @@ class MCConfig(object): cursor = dbconnection.cursor() cursor.execute("SELECT MCconfig FROM GeneralInfo") result = cursor.fetchone() - self.jsonMCConfig = json.load(open(result[0])) + self.jsonMCConfig = json.loads(result[0]) class MemSpec(object): @@ -39,7 +39,7 @@ class MemSpec(object): cursor = dbconnection.cursor() cursor.execute("SELECT Memspec FROM GeneralInfo") result = cursor.fetchone() - self.jsonMemSpec = json.load(open(result[0])) + self.jsonMemSpec = json.loads(result[0]) def getClock(dbconnection): diff --git a/DRAMSys/traceAnalyzer/tracefiletab.cpp b/DRAMSys/traceAnalyzer/tracefiletab.cpp index 842c1760..36c95509 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.cpp +++ b/DRAMSys/traceAnalyzer/tracefiletab.cpp @@ -59,11 +59,15 @@ #include "qwt_plot_magnifier.h" #include "qwt_plot_panner.h" #include "presentation/traceselector.h" +#include "businessObjects/configmodels.h" #include TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) : - QWidget(parent), ui(new Ui::TraceFileTab), savingChangesToDB(false) + QWidget(parent), ui(new Ui::TraceFileTab), navigator(new TraceNavigator(path, this)), + mcConfigModel(new McConfigModel(navigator->TraceFile(), this)), + memSpecModel(new MemSpecModel(navigator->TraceFile(), this)), + savingChangesToDB(false) { ui->setupUi(this); this->path = path; @@ -79,6 +83,12 @@ TraceFileTab::TraceFileTab(QWidget *parent, const QString &path) : ui->fileDescriptionEdit->setPlainText( navigator->GeneralTraceInfo().description); + ui->mcConfigView->setModel(mcConfigModel); + ui->mcConfigView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); + + ui->memSpecView->setModel(memSpecModel); + ui->memSpecView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); + tracefileChanged(); } @@ -122,8 +132,6 @@ void TraceFileTab::setUpTraceplotScrollbar() void TraceFileTab::initNavigatorAndItsDependentWidgets(QString path) { - navigator = new TraceNavigator(path, this); - ui->traceplot->init(navigator, ui->traceplotScrollbar); ui->traceScroller->init(navigator, ui->traceplot); diff --git a/DRAMSys/traceAnalyzer/tracefiletab.h b/DRAMSys/traceAnalyzer/tracefiletab.h index 25fa915c..966d5784 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.h +++ b/DRAMSys/traceAnalyzer/tracefiletab.h @@ -45,6 +45,7 @@ #include "presentation/tracenavigator.h" #include "presentation/traceplot.h" #include "presentation/tracescroller.h" +#include "businessObjects/configmodels.h" namespace Ui { class TraceFileTab; @@ -74,6 +75,10 @@ private: Ui::TraceFileTab *ui; TraceNavigator *navigator; QFileSystemWatcher *fileWatcher; + + QAbstractItemModel *mcConfigModel; + QAbstractItemModel *memSpecModel; + void setUpQueryEditor(QString path); bool savingChangesToDB; diff --git a/DRAMSys/traceAnalyzer/tracefiletab.ui b/DRAMSys/traceAnalyzer/tracefiletab.ui index cd45bbef..64693bdb 100644 --- a/DRAMSys/traceAnalyzer/tracefiletab.ui +++ b/DRAMSys/traceAnalyzer/tracefiletab.ui @@ -348,6 +348,39 @@ + + + Configuration + + + + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + true + + + false + + + + + + + true + + + + +