[WIP] Initial commit for windowed plot
WIP given that we still need to implement resampling for the windowed series to avoid massive slowdown on large programs.
MODIFY
src/cachesim/cacheplotwidget.cpp
src/cachesim/cacheplotwidget.cpp
#include "cacheplotwidget.h"
#include "ui_cacheplotwidget.h"
+#include <QCheckBox>
#include <QClipboard>
#include <QFileDialog>
#include <QPushButton>
@@ -44,6 +45,8 @@ CachePlotWidget::CachePlotWidget(QWidget* parent) : QWidget(parent), m_ui(new Ui
connect(m_ui->num, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CachePlotWidget::variablesChanged);
connect(m_ui->den, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &CachePlotWidget::variablesChanged);
+ connect(m_ui->windowed, &QCheckBox::toggled, this, &CachePlotWidget::variablesChanged);
+ connect(m_ui->windowCycles, QOverload<int>::of(&QSpinBox::valueChanged), this, &CachePlotWidget::variablesChanged);
m_ui->rangeMin->setValue(0);
m_ui->rangeMax->setValue(ProcessorHandler::getProcessor()->getCycleCount());
@@ -54,6 +57,7 @@ CachePlotWidget::CachePlotWidget(QWidget* parent) : QWidget(parent), m_ui(new Ui
const QIcon sizeBreakdownIcon = QIcon(":/icons/info.svg");
m_ui->sizeBreakdownButton->setIcon(sizeBreakdownIcon);
connect(m_ui->sizeBreakdownButton, &QPushButton::clicked, this, &CachePlotWidget::showSizeBreakdown);
+ connect(m_ui->windowed, &QCheckBox::toggled, m_ui->windowCycles, &QWidget::setEnabled);
}
void CachePlotWidget::showSizeBreakdown() {
@@ -83,7 +87,11 @@ void CachePlotWidget::setCache(std::shared_ptr<CacheSim> cache) {
m_plot = new QChart();
m_series = new QLineSeries(m_plot);
+ m_series->setName("Total");
m_plot->addSeries(m_series);
+ m_windowSeries = new QLineSeries(m_plot);
+ m_windowSeries->setName("Moving avg.");
+ m_plot->addSeries(m_windowSeries);
m_plot->createDefaultAxes();
m_plot->legend()->hide();
m_ui->plotView->setPlot(m_plot);
@@ -239,12 +247,25 @@ void CachePlotWidget::updateRatioPlot() {
return;
}
+ // convenience function to move a series on/off the chart based on the number of points to be added.
+ // We have to remove series due to append(QList(...)) calling redraw _for each_ point in the list.
+ // Not removing the series for low nNewPoints avoids a flicker in plot labels. Everything is a balance...
+ const auto plotMover = [=](QLineSeries* series, bool visible) {
+ if (nNewPoints > 2) {
+ if (visible) {
+ this->m_plot->addSeries(series);
+ } else {
+ this->m_plot->removeSeries(series);
+ }
+ }
+ };
+
const auto& numerator = newCacheData.at(m_numerator);
const auto& denominator = newCacheData.at(m_denominator);
m_lastCyclePlotted = numerator.last().x();
QList<QPointF> newPoints;
- newPoints.reserve(2 * nNewPoints);
+ QList<QPointF> newWindowPoints;
QPointF lastPoint;
if (m_series->pointsVector().size() > 0) {
lastPoint = m_series->pointsVector().last();
@@ -252,13 +273,14 @@ void CachePlotWidget::updateRatioPlot() {
lastPoint = QPointF(-1, 0);
}
for (int i = 0; i < nNewPoints; i++) {
+ // Cummulative plot
const auto& p1 = numerator.at(i);
const auto& p2 = denominator.at(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;
+ ratio *= 100.0;
}
const QPointF newPoint = QPointF(p1.x(), ratio);
if (lastPoint.x() >= 0) {
@@ -272,14 +294,40 @@ void CachePlotWidget::updateRatioPlot() {
m_maxY = ratio > m_maxY ? ratio : m_maxY;
m_minY = ratio < m_minY ? ratio : m_minY;
lastPoint = newPoint;
+
+ // Windowed plot
+ if (m_ui->windowed->isChecked()) {
+ const QPoint dNum = p1 - m_lastData.first;
+ const QPoint dDen = p2 - m_lastData.second;
+ double wRatio = 0;
+ if (dDen.y() != 0) {
+ wRatio = static_cast<double>(dNum.y()) / dDen.y();
+ wRatio *= 100.0;
+ }
+
+ m_maxY = wRatio > m_maxY ? wRatio : m_maxY;
+ m_minY = wRatio < m_minY ? wRatio : m_minY;
+
+ m_windowData.push(wRatio);
+
+ // Plot moving average
+ const double wAvg = std::accumulate(m_windowData.begin(), m_windowData.end(), 0.0) / m_windowData.size();
+ newWindowPoints << QPointF(p1.x(), wAvg);
+ m_lastData.first = p1;
+ m_lastData.second = p2;
+ }
}
if (newPoints.size() == 0) {
return;
}
- // Have to remove series due to append(QList(...)) calling redraw _for each_ point in the list
- m_plot->removeSeries(m_series);
+
+ plotMover(m_series, false);
m_series->append(newPoints);
+ if (m_ui->windowed->isChecked()) {
+ plotMover(m_windowSeries, false);
+ m_windowSeries->append(newWindowPoints);
+ }
// Determine whether to resample; *2 the allowed points to account for the addition of step points.
const int maxPoints = m_ui->plotView->width() * 2;
@@ -287,7 +335,11 @@ void CachePlotWidget::updateRatioPlot() {
resample(m_series, maxPoints / 2, m_xStep);
}
- m_plot->addSeries(m_series);
+ plotMover(m_series, true);
+ if (m_ui->windowed->isChecked()) {
+ plotMover(m_windowSeries, true);
+ }
+
m_plot->createDefaultAxes();
const unsigned maxX = ProcessorHandler::getProcessor()->getCycleCount();
@@ -321,9 +373,19 @@ void CachePlotWidget::resetRatioPlot() {
m_maxY = -DBL_MAX;
m_minY = DBL_MAX;
m_series->clear();
+ m_windowSeries->clear();
m_lastCyclePlotted = 0;
m_xStep = 1;
+ if (m_ui->windowed->isChecked()) {
+ m_windowData = FixedQueue<double>(m_ui->windowCycles->value());
+ m_windowSeries->setVisible(true);
+ m_plot->legend()->setVisible(true);
+ } else {
+ m_windowSeries->setVisible(false);
+ m_plot->legend()->setVisible(false);
+ }
+
updateRatioPlot();
}

MODIFY
src/cachesim/cacheplotwidget.h
src/cachesim/cacheplotwidget.h
#include <QWidget>
#include <QtCharts/QChartGlobal>
+#include <queue>
#include "cachesim.h"
#include "float.h"
@@ -18,6 +19,21 @@ QT_CHARTS_END_NAMESPACE
QT_CHARTS_USE_NAMESPACE
+template <typename T>
+class FixedQueue : public std::deque<T> {
+public:
+ FixedQueue(const unsigned N = 1) : m_n(N) {}
+ void push(const T& value) {
+ if (this->size() == m_n) {
+ this->pop_front();
+ }
+ std::deque<T>::push_back(value);
+ }
+
+private:
+ unsigned m_n;
+};
+
namespace Ripes {
namespace Ui {
@@ -68,6 +84,12 @@ private:
double m_xStep = 1.0;
static constexpr int s_resamplingRatio = 2;
+ QLineSeries* m_windowSeries = nullptr;
+ // N last computations of the change in ratio value
+ FixedQueue<double> m_windowData;
+ // Last cycle numerator and denominator values
+ std::pair<QPoint, QPoint> m_lastData;
+
Ui::CachePlotWidget* m_ui;
std::shared_ptr<CacheSim> m_cache;

MODIFY
src/cachesim/cacheplotwidget.ui
src/cachesim/cacheplotwidget.ui
<rect>
<x>0</x>
<y>0</y>
- <width>714</width>
+ <width>733</width>
<height>330</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
- <item row="1" column="2">
- <widget class="QLabel" name="label_2">
- <property name="text">
- <string>Denominator</string>
- </property>
- </widget>
+ <item row="1" column="3">
+ <widget class="QComboBox" name="den"/>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label">
</property>
</widget>
</item>
+ <item row="1" column="1">
+ <widget class="QSpinBox" name="rangeMax">
+ <property name="maximum">
+ <number>999999999</number>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Denominator</string>
+ </property>
+ </widget>
+ </item>
<item row="0" column="0">
<widget class="QLabel" name="label_6">
<property name="text">
</property>
</widget>
</item>
- <item row="1" column="1">
- <widget class="QSpinBox" name="rangeMax">
- <property name="maximum">
- <number>999999999</number>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_7">
+ <property name="text">
+ <string>Cycles max.</string>
</property>
</widget>
</item>
+ <item row="0" column="3">
+ <widget class="QComboBox" name="num"/>
+ </item>
<item row="0" column="1">
<widget class="QSpinBox" name="rangeMin">
<property name="maximum">
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="label_7">
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="windowed">
<property name="text">
- <string>Cycles max.</string>
+ <string>Moving avg.</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
</property>
</widget>
</item>
- <item row="0" column="3">
- <widget class="QComboBox" name="num"/>
- </item>
- <item row="1" column="3">
- <widget class="QComboBox" name="den"/>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="windowCycles">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>999</number>
+ </property>
+ <property name="value">
+ <number>50</number>
+ </property>
+ </widget>
</item>
</layout>
</item>

[WIP] Initial commit for windowed plot

WIP given that we still need to implement resampling for the windowed series to avoid massive slowdown on large programs.