Initial commit for CachePlotWidget
MODIFY
.travis.yml
.travis.yml
@@ -33,6 +33,7 @@ matrix:
packages:
- qt510-meta-minimal
- qt510svg
+ - qt510charts-no-lgpl
- libc6-dev
- g++-8
- tree
@@ -53,6 +54,7 @@ matrix:
packages:
- qt511-meta-minimal
- qt511svg
+ - qt511charts-no-lgpl
- libc6-dev
- g++-8
- tree

MODIFY
CMakeLists.txt
CMakeLists.txt
@@ -18,13 +18,16 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
-# Find Qt5Core and Qt5Widgets
+# Find required Qt packages
find_package(Qt5Core REQUIRED)
find_package(Qt5Widgets CONFIG REQUIRED)
+find_package(Qt5Svg REQUIRED)
+find_package(Qt5Charts CONFIG REQUIRED)
# Finding Qt includes
include_directories(${Qt5Widgets_INCLUDE_DIRS})
include_directories(${Qt5Core_INCLUDE_DIRS})
+include_directories(${Qt5Charts_INCLUDE_DIRS})
######################################################################
## Resources setup

ADD
resources/icons/analytics.svg
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
+<g>
+ <path style="fill:#F0C419;" d="M308.966,194.207L150.069,79.448l-88.276,97.103l-13.977-1.471l0.736,102.989v167.724
+ c0.029,9.739,7.916,17.627,17.655,17.655H512V88.276L308.966,194.207z"/>
+ <path style="fill:#3B97D3;" d="M512,450.207v44.138c-0.029,9.739-7.916,17.627-17.655,17.655H17.655
+ C7.916,511.971,0.029,504.084,0,494.345V17.655C0.028,7.916,7.916,0.028,17.655,0h26.483c9.739,0.028,17.627,7.916,17.655,17.655
+ v414.897c0.029,9.739,7.916,17.626,17.655,17.655H512z"/>
+ <path style="fill:#955BA5;" d="M512,353.103v97.103H79.448c-9.739-0.029-17.627-7.916-17.655-17.655v-52.966l185.379-61.793
+ l132.414,70.621L512,353.103z"/>
+ <polygon style="fill:#E64C3C;" points="512,79.448 512,220.69 370.759,291.31 211.862,211.862 61.793,264.828 61.793,167.724
+ 150.069,70.621 308.966,185.379 "/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>

MODIFY
resources/icons/icons.qrc
resources/icons/icons.qrc
<file>notepad.svg</file>
<file>plus.svg</file>
<file>delete.svg</file>
+ <file>analytics.svg</file>
</qresource>
</RCC>

MODIFY
scripts/windows/before_install.sh
scripts/windows/before_install.sh
@@ -12,7 +12,7 @@ curl -vLO https://code.qt.io/cgit/qbs/qbs.git/plain/scripts/install-qt.sh
bash install-qt.sh \
--version ${QT_VERSION} \
--toolchain ${QT_TOOLCHAIN}\
- qtbase qttools svg
+ qtbase qttools svg qtcharts
choco install zip

MODIFY
src/CMakeLists.txt
src/CMakeLists.txt
@@ -13,7 +13,7 @@ target_compile_features(${RIPES_LIB} PRIVATE cxx_std_17)
# Link external libraries
target_link_libraries(${RIPES_LIB} fancytabbar_lib)
-target_link_libraries(${RIPES_LIB} ${VSRTL_GRAPHICS_LIB})
+target_link_libraries(${RIPES_LIB} ${VSRTL_GRAPHICS_LIB} Qt5::Charts)
add_subdirectory(processors)

MODIFY
src/cacheconfigwidget.cpp
src/cacheconfigwidget.cpp
#include <QMessageBox>
#include <QSpinBox>
#include <QTimer>
+#include <QtCharts/QChartView>
-namespace Ripes {
-
-template <typename Enum>
-void setupEnumCombobox(QComboBox* combobox, std::map<Enum, QString>& nameMap) {
- for (const auto& iter : nameMap) {
- combobox->addItem(iter.second, QVariant::fromValue(iter.first));
- }
-}
+#include "cacheplotwidget.h"
+#include "enumcombobox.h"
-template <typename Enum>
-void setEnumIndex(QComboBox* combobox, Enum enumItem) {
- for (int i = 0; i < combobox->count(); i++) {
- if (qvariant_cast<Enum>(combobox->itemData(i)) == enumItem) {
- combobox->setCurrentIndex(i);
- return;
- }
- }
- Q_ASSERT(false && "Index not found");
-}
+namespace Ripes {
CacheConfigWidget::CacheConfigWidget(QWidget* parent) : QWidget(parent), m_ui(new Ui::CacheConfigWidget) {
m_ui->setupUi(this);
@@ -35,6 +21,10 @@ void CacheConfigWidget::setCache(CacheSim* cache) {
const QIcon sizeBreakdownIcon = QIcon(":/icons/info.svg");
m_ui->sizeBreakdownButton->setIcon(sizeBreakdownIcon);
+ const QIcon plotIcon = QIcon(":/icons/analytics.svg");
+ m_ui->cachePlot->setIcon(plotIcon);
+ connect(m_ui->cachePlot, &QPushButton::clicked, this, &CacheConfigWidget::showCachePlot);
+
setupEnumCombobox(m_ui->replacementPolicy, s_cacheReplPolicyStrings);
setupEnumCombobox(m_ui->wrHit, s_cacheWritePolicyStrings);
setupEnumCombobox(m_ui->wrMiss, s_cacheWriteAllocateStrings);
@@ -112,6 +102,11 @@ void CacheConfigWidget::setCache(CacheSim* cache) {
});
}
+void CacheConfigWidget::showCachePlot() {
+ CachePlotWidget plotWidget(*m_cache);
+ plotWidget.exec();
+}
+
void CacheConfigWidget::setupPresets() {
std::vector<std::pair<QString, CacheSim::CachePreset>> presets;

MODIFY
src/cacheconfigwidget.h
src/cacheconfigwidget.h
@@ -21,6 +21,7 @@ public:
public slots:
void updateHitrate();
void configChanged();
+ void showCachePlot();
private:
void updateCacheSize();

MODIFY
src/cacheconfigwidget.ui
src/cacheconfigwidget.ui
<string>Statistics:</string>
</property>
<layout class="QGridLayout" name="gridLayout_5">
- <item row="2" column="0">
- <widget class="QPushButton" name="randomwrite">
- <property name="text">
- <string>Random write</string>
- </property>
- </widget>
- </item>
- <item row="3" column="0">
- <widget class="QPushButton" name="undo">
- <property name="text">
- <string>Undo</string>
- </property>
- </widget>
- </item>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
</item>
</layout>
</item>
- <item row="5" column="0">
+ <item row="6" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</spacer>
</item>
- <item row="1" column="0">
+ <item row="5" column="0">
+ <widget class="QPushButton" name="autoAccess">
+ <property name="text">
+ <string>auto</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QPushButton" name="randomwrite">
+ <property name="text">
+ <string>Random write</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
<widget class="QPushButton" name="randomread">
<property name="text">
<string>Random read</string>
</widget>
</item>
<item row="4" column="0">
- <widget class="QPushButton" name="autoAccess">
+ <widget class="QPushButton" name="undo">
<property name="text">
- <string>auto</string>
+ <string>Undo</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QToolButton" name="cachePlot">
+ <property name="text">
+ <string>...</string>
</property>
</widget>
</item>

ADD
src/cacheplotwidget.cpp
+#include "cacheplotwidget.h"
+#include "ui_cacheplotwidget.h"
+
+#include <QToolBar>
+#include <QtCharts/QChartView>
+#include <QtCharts/QLineSeries>
+#include <QtCharts/QValueAxis>
+
+#include "enumcombobox.h"
+
+#include "limits.h"
+
+namespace Ripes {
+
+CachePlotWidget::CachePlotWidget(const CacheSim& sim, QWidget* parent)
+ : QDialog(parent), m_ui(new Ui::CachePlotWidget), m_cache(sim) {
+ m_ui->setupUi(this);
+ setWindowTitle("Cache Access Statistics");
+
+ m_toolbar = new QToolBar(this);
+ m_ui->toolbarLayout->addWidget(m_toolbar);
+ setupToolbar();
+
+ setupEnumCombobox(m_ui->num, s_cacheVariableStrings);
+ setupEnumCombobox(m_ui->den, s_cacheVariableStrings);
+ setupEnumCombobox(m_ui->plotType, s_cachePlotTypeStrings);
+
+ setupStackedVariablesList();
+
+ // Set default ratio plot to be hit rate
+ setEnumIndex(m_ui->num, Variable::Hits);
+ setEnumIndex(m_ui->den, Variable::Accesses);
+
+ connect(m_ui->num, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CachePlotWidget::variablesChanged);
+ connect(m_ui->den, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CachePlotWidget::variablesChanged);
+
+ const auto& accessTrace = m_cache.getAccessTrace();
+ m_ui->rangeMin->setValue(0);
+ m_ui->rangeMax->setValue(accessTrace.size());
+
+ connect(m_ui->rangeMin, QOverload<int>::of(&QSpinBox::valueChanged), this, &CachePlotWidget::rangeChanged);
+ connect(m_ui->rangeMax, QOverload<int>::of(&QSpinBox::valueChanged), this, &CachePlotWidget::rangeChanged);
+
+ connect(m_ui->plotType, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
+ &CachePlotWidget::plotTypeChanged);
+
+ // Synchronize widget state
+ plotTypeChanged();
+ variablesChanged();
+ rangeChanged();
+}
+
+CachePlotWidget::~CachePlotWidget() {
+ delete m_ui;
+}
+
+void CachePlotWidget::setupStackedVariablesList() {
+ for (const auto& iter : s_cacheVariableStrings) {
+ auto* stackedVariableItem = new QListWidgetItem(iter.second);
+ stackedVariableItem->setData(Qt::UserRole, iter.second);
+ stackedVariableItem->setCheckState(Qt::Unchecked);
+ m_ui->stackedVariables->addItem(stackedVariableItem);
+ }
+}
+
+void CachePlotWidget::setupToolbar() {
+ const QIcon copyIcon = QIcon(":/icons/documents.svg");
+ m_copyDataAction = new QAction("Copy plot data to clipboard", this);
+ m_copyDataAction->setIcon(copyIcon);
+ m_toolbar->addAction(m_copyDataAction);
+
+ const QIcon saveIcon = QIcon(":/icons/save.svg");
+ m_savePlotAction = new QAction("Save plot to file", this);
+ m_savePlotAction->setIcon(saveIcon);
+ m_toolbar->addAction(m_savePlotAction);
+}
+
+void CachePlotWidget::plotTypeChanged() {
+ m_plotType = getEnumValue<PlotType>(m_ui->plotType);
+
+ if (m_plotType == PlotType::Ratio) {
+ m_ui->configWidget->setCurrentWidget(m_ui->ratioConfigPage);
+ } else if (m_plotType == PlotType::Stacked) {
+ m_ui->configWidget->setCurrentWidget(m_ui->stackedConfigPage);
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
+void CachePlotWidget::rangeChanged() {
+ if (m_currentPlot) {
+ m_currentPlot->axes(Qt::Horizontal).first()->setRange(m_ui->rangeMin->value(), m_ui->rangeMax->value());
+ }
+
+ // Update allowed ranges
+ const auto& accessTrace = m_cache.getAccessTrace();
+ m_ui->rangeMin->setMinimum(0);
+ m_ui->rangeMin->setMaximum(m_ui->rangeMax->value());
+ m_ui->rangeMax->setMinimum(m_ui->rangeMin->value());
+ m_ui->rangeMax->setMaximum(accessTrace.size());
+}
+
+void CachePlotWidget::variablesChanged() {
+ if (m_plotType == PlotType::Ratio) {
+ const Variable numerator = getEnumValue<Variable>(m_ui->num);
+ const Variable denominator = getEnumValue<Variable>(m_ui->den);
+ setPlot(numerator, denominator);
+ }
+}
+
+QMap<CachePlotWidget::Variable, QList<QPoint>> CachePlotWidget::gatherData(const std::set<Variable> types) const {
+ const auto& trace = m_cache.getAccessTrace();
+
+ QMap<CachePlotWidget::Variable, QList<QPoint>> data;
+
+ for (const auto& type : types) {
+ // Initialize all data types
+ data[type];
+ }
+
+ // Gather data
+ for (const auto& entry : trace) {
+ if (types.count(Variable::Writes)) {
+ data[Variable::Writes].append(QPoint(entry.first, entry.second.writes));
+ }
+ if (types.count(Variable::Reads)) {
+ data[Variable::Reads].append(QPoint(entry.first, entry.second.reads));
+ }
+ if (types.count(Variable::Hits)) {
+ data[Variable::Hits].append(QPoint(entry.first, entry.second.hits));
+ }
+ if (types.count(Variable::Misses)) {
+ data[Variable::Misses].append(QPoint(entry.first, entry.second.misses));
+ }
+ if (types.count(Variable::Writebacks)) {
+ data[Variable::Writebacks].append(QPoint(entry.first, entry.second.writebacks));
+ }
+ if (types.count(Variable::Accesses)) {
+ data[Variable::Accesses].append(QPoint(entry.first, entry.second.hits + entry.second.misses));
+ }
+ }
+
+ return data;
+}
+
+QChart* CachePlotWidget::createRatioPlot(const Variable num, const Variable den) const {
+ const auto data = gatherData({num, den});
+
+ const QList<QPoint>& numerator = data[num];
+ const QList<QPoint>& denominator = data[den];
+
+ Q_ASSERT(numerator.size() == denominator.size());
+
+ const unsigned points = numerator.size();
+
+ QChart* chart = new QChart();
+ chart->setTitle(s_cacheVariableStrings[num] + "/" + s_cacheVariableStrings[den]);
+
+ QLineSeries* series = new QLineSeries(chart);
+ double maxval = 0;
+ for (int i = 0; i < points; i++) {
+ const auto& p1 = numerator[i];
+ const auto& p2 = denominator[i];
+ Q_ASSERT(p1.x() == p2.x() && "Data inconsistency");
+ double ratio = 0;
+ if (p2.y() != 0) {
+ ratio = static_cast<double>(p1.y()) / p2.y();
+ ratio *= 100;
+ }
+ series->append(p1.x(), ratio);
+ maxval = ratio > maxval ? ratio : maxval;
+ }
+
+ chart->addSeries(series);
+
+ chart->createDefaultAxes();
+ chart->axes(Qt::Horizontal).first()->setRange(0, points);
+ chart->axes(Qt::Vertical).first()->setRange(0, maxval * 1.1);
+
+ chart->legend()->setEnabled(false);
+
+ // Add space to label to add space between labels and axis
+ QValueAxis* axisY = qobject_cast<QValueAxis*>(chart->axes(Qt::Vertical).first());
+ QValueAxis* axisX = qobject_cast<QValueAxis*>(chart->axes(Qt::Horizontal).first());
+ Q_ASSERT(axisY);
+ axisY->setLabelFormat("%.1f ");
+ axisY->setTitleText("%");
+
+ axisX->setLabelFormat("%d ");
+ axisX->setTitleText("Cycle");
+
+ //![4]
+
+ return chart;
+}
+
+void CachePlotWidget::setPlot(const Variable num, const Variable den) {
+ const auto& accessTrace = m_cache.getAccessTrace();
+
+ auto* oldChart = m_ui->plotView->chart();
+ m_currentPlot = createRatioPlot(num, den);
+ m_ui->plotView->setChart(m_currentPlot);
+ if (oldChart) {
+ delete oldChart;
+ }
+}
+
+} // namespace Ripes

ADD
src/cacheplotwidget.h
+#pragma once
+
+#include <QDialog>
+#include <QMetaType>
+#include <QtCharts/QChartGlobal>
+
+#include "cachesim.h"
+
+QT_FORWARD_DECLARE_CLASS(QToolBar);
+QT_FORWARD_DECLARE_CLASS(QAction);
+
+QT_CHARTS_BEGIN_NAMESPACE
+class QChartView;
+class QChart;
+QT_CHARTS_END_NAMESPACE
+
+QT_CHARTS_USE_NAMESPACE
+
+namespace Ripes {
+
+namespace Ui {
+class CachePlotWidget;
+}
+
+class CachePlotWidget : public QDialog {
+ Q_OBJECT
+
+public:
+ enum class Variable { Writes, Reads, Hits, Misses, Writebacks, Accesses };
+ enum class PlotType { Ratio, Stacked };
+ explicit CachePlotWidget(const CacheSim& sim, QWidget* parent = nullptr);
+ ~CachePlotWidget();
+
+public slots:
+
+private slots:
+ void variablesChanged();
+ void rangeChanged();
+ void plotTypeChanged();
+
+private:
+ /**
+ * @brief gatherData
+ * @returns a list of QPoints containing plotable data gathered from the cache simulator, as per the specified
+ * @param types.
+ */
+ QMap<Variable, QList<QPoint>> gatherData(const std::set<Variable> types) const;
+ void setupToolbar();
+ void setupStackedVariablesList();
+ void setPlot(const Variable num, const Variable den);
+
+ QChart* createRatioPlot(const Variable num, const Variable den) const;
+
+ PlotType m_plotType = PlotType::Ratio;
+ QChart* m_currentPlot = nullptr;
+
+ Ui::CachePlotWidget* m_ui;
+ const CacheSim& m_cache;
+
+ QToolBar* m_toolbar = nullptr;
+ QAction* m_copyDataAction = nullptr;
+ QAction* m_savePlotAction = nullptr;
+};
+
+static std::map<CachePlotWidget::Variable, QString> s_cacheVariableStrings{
+ {CachePlotWidget::Variable::Writes, "Writes"},
+ {CachePlotWidget::Variable::Reads, "Reads"},
+ {CachePlotWidget::Variable::Hits, "Hits"},
+ {CachePlotWidget::Variable::Misses, "Misses"},
+ {CachePlotWidget::Variable::Writebacks, "Writebacks"},
+ {CachePlotWidget::Variable::Accesses, "Accesses"}};
+
+static std::map<CachePlotWidget::PlotType, QString> s_cachePlotTypeStrings{
+ {CachePlotWidget::PlotType::Ratio, "Ratio"},
+ {CachePlotWidget::PlotType::Stacked, "Stacked"}};
+
+} // namespace Ripes
+
+Q_DECLARE_METATYPE(Ripes::CachePlotWidget::Variable);
+Q_DECLARE_METATYPE(Ripes::CachePlotWidget::PlotType);

ADD
src/cacheplotwidget.ui
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Ripes::CachePlotWidget</class>
+ <widget class="QDialog" name="Ripes::CachePlotWidget">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>893</width>
+ <height>536</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Dialog</string>
+ </property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QGridLayout" name="toolbarLayout"/>
+ </item>
+ <item>
+ <widget class="Line" name="line_2">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <layout class="QGridLayout" name="gridLayout_3">
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Plot type</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="rangeMin">
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_6">
+ <property name="text">
+ <string>Cycles min.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="plotType"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Cycles max.</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="rangeMax">
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="Line" name="line">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QStackedWidget" name="configWidget">
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <widget class="QWidget" name="stackedConfigPage">
+ <layout class="QGridLayout" name="gridLayout_6">
+ <item row="0" column="0">
+ <widget class="QListWidget" name="stackedVariables"/>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="ratioConfigPage">
+ <layout class="QGridLayout" name="gridLayout_5">
+ <item row="0" column="0">
+ <layout class="QGridLayout" name="gridLayout_4">
+ <item row="0" column="1">
+ <widget class="QComboBox" name="num"/>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Numerator</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Denominator</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="den"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout" stretch="0,1">
+ <item>
+ <layout class="QGridLayout" name="gridLayout_2"/>
+ </item>
+ <item>
+ <widget class="QtCharts::QChartView" name="plotView" native="true"/>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>QtCharts::QChartView</class>
+ <extends>QWidget</extends>
+ <header>QtCharts/QChartView</header>
+ <container>1</container>
+ </customwidget>
+ </customwidgets>
+ <resources/>
+ <connections/>
+</ui>

MODIFY
src/cachesim.cpp
src/cachesim.cpp
@@ -154,28 +154,28 @@ CacheSim::CacheWay CacheSim::evictAndUpdate(CacheTransaction& transaction) {
}
unsigned CacheSim::getHits() const {
- if (m_hitTrace.size() == 0) {
+ if (m_accessTrace.size() == 0) {
return 0;
} else {
- auto& trace = m_hitTrace.rbegin()->second;
+ auto& trace = m_accessTrace.rbegin()->second;
return trace.hits;
}
}
unsigned CacheSim::getMisses() const {
- if (m_hitTrace.size() == 0) {
+ if (m_accessTrace.size() == 0) {
return 0;
} else {
- auto& trace = m_hitTrace.rbegin()->second;
+ auto& trace = m_accessTrace.rbegin()->second;
return trace.misses;
}
}
double CacheSim::getHitRate() const {
- if (m_hitTrace.size() == 0) {
+ if (m_accessTrace.size() == 0) {
return 0;
} else {
- auto& trace = m_hitTrace.rbegin()->second;
+ auto& trace = m_accessTrace.rbegin()->second;
return static_cast<double>(trace.hits) / (trace.hits + trace.misses);
}
}
@@ -197,10 +197,11 @@ void CacheSim::analyzeCacheAccess(CacheTransaction& transaction) const {
}
void CacheSim::updateHitTrace(const CacheTransaction& transaction) {
- if (m_hitTrace.size() == 0) {
- m_hitTrace[0] = CacheHitTrace(transaction.isHit);
+ if (m_accessTrace.size() == 0) {
+ m_accessTrace[0] = CacheAccessTrace(transaction.isHit);
} else {
- m_hitTrace[m_hitTrace.size()] = CacheHitTrace(m_hitTrace[m_hitTrace.size() - 1], transaction.isHit);
+ m_accessTrace[m_accessTrace.size()] =
+ CacheAccessTrace(m_accessTrace[m_accessTrace.size() - 1], transaction.type, transaction.isHit, false);
}
emit hitrateChanged();
}
@@ -355,7 +356,7 @@ const CacheSim::CacheLine* CacheSim::getLine(unsigned idx) const {
void CacheSim::updateConfiguration() {
// Cache configuration changes shall enforce a full reset of the computing system
m_cacheLines.clear();
- m_hitTrace.clear();
+ m_accessTrace.clear();
m_traceStack.clear();
// Recalculate masks

MODIFY
src/cachesim.h
src/cachesim.h
@@ -67,6 +67,26 @@ public:
bool tagChanged = false; // True if transToValid or the previous entry was evicted
};
+ struct CacheAccessTrace {
+ int hits = 0;
+ int misses = 0;
+ int reads = 0;
+ int writes = 0;
+ int writebacks = 0;
+ CacheAccessTrace() {}
+ CacheAccessTrace(bool hit) {
+ hits = hit ? 1 : 0;
+ misses = hit ? 0 : 1;
+ }
+ CacheAccessTrace(const CacheAccessTrace& pre, AccessType type, bool hit, bool writeback) {
+ reads = pre.reads + (type == AccessType::Read ? 1 : 0);
+ writes = pre.writes + (type == AccessType::Write ? 1 : 0);
+ writebacks = pre.writebacks + (writeback ? 1 : 0);
+ hits = pre.hits + (hit ? 1 : 0);
+ misses = pre.misses + (hit ? 0 : 1);
+ }
+ };
+
using CacheLine = std::map<unsigned, CacheWay>;
CacheSim(QObject* parent);
@@ -94,6 +114,8 @@ public:
ReplPolicy getReplacementPolicy() const { return m_replPolicy; }
WritePolicy getWritePolicy() const { return m_wrPolicy; }
+ const std::map<unsigned, CacheAccessTrace>& getAccessTrace() const { return m_accessTrace; }
+
double getHitRate() const;
unsigned getHits() const;
unsigned getMisses() const;
@@ -165,20 +187,7 @@ private:
*/
void revertCacheLineReplFields(CacheLine& line, const CacheWay& oldWay, unsigned wayIdx);
- struct CacheHitTrace {
- int hits = 0;
- int misses = 0;
- CacheHitTrace() {}
- CacheHitTrace(bool hit) {
- hits = hit ? 1 : 0;
- misses = hit ? 0 : 1;
- }
- CacheHitTrace(const CacheHitTrace& pre, bool hit) {
- hits = pre.hits + (hit ? 1 : 0);
- misses = pre.misses + (hit ? 0 : 1);
- }
- };
- std::map<unsigned, CacheHitTrace> m_hitTrace;
+ std::map<unsigned, CacheAccessTrace> m_accessTrace;
// Cache access trace
// The following information is used to track all most-recent modifications (up to a given set constant) made to the

ADD
src/enumcombobox.h
+#pragma once
+
+#include <QComboBox>
+#include <QString>
+#include <map>
+
+namespace Ripes {
+
+template <typename Enum>
+void setupEnumCombobox(QComboBox* combobox, std::map<Enum, QString>& nameMap) {
+ for (const auto& iter : nameMap) {
+ combobox->addItem(iter.second, QVariant::fromValue(iter.first));
+ }
+}
+
+template <typename Enum>
+void setEnumIndex(QComboBox* combobox, Enum enumItem) {
+ for (int i = 0; i < combobox->count(); i++) {
+ if (qvariant_cast<Enum>(combobox->itemData(i)) == enumItem) {
+ combobox->setCurrentIndex(i);
+ return;
+ }
+ }
+ Q_ASSERT(false && "Index not found");
+}
+
+template <typename Enum>
+Enum getEnumValue(QComboBox* combobox) {
+ return qvariant_cast<Enum>(combobox->itemData(combobox->currentIndex()));
+}
+
+} // namespace Ripes

Initial commit for CachePlotWidget