Integrate cache simulator with VSRTL processor cycle undoing
MODIFY
src/cachesim/cachegraphic.cpp
src/cachesim/cachegraphic.cpp
@@ -166,22 +166,27 @@ std::unique_ptr<QGraphicsSimpleTextItem> CacheGraphic::createGraphicsTextItemSP(
void CacheGraphic::cacheInvalidated() {
for (int lineIdx = 0; lineIdx < m_cache.getLines(); lineIdx++) {
- const auto* line = m_cache.getLine(lineIdx);
+ if (const auto* line = m_cache.getLine(lineIdx)) {
for (const auto& way : *line) {
wayInvalidated(lineIdx, way.first);
}
updateLineReplFields(lineIdx);
}
}
+}
void CacheGraphic::wayInvalidated(unsigned lineIdx, unsigned wayIdx) {
updateWay(lineIdx, wayIdx);
updateLineReplFields(lineIdx);
}
-void CacheGraphic::dataChanged(const CacheSim::CacheTransaction& transaction) {
- wayInvalidated(transaction.index.line, transaction.index.way);
- updateHighlighting(true, &transaction);
+void CacheGraphic::dataChanged(const CacheSim::CacheTransaction* transaction) {
+ if (transaction != nullptr) {
+ wayInvalidated(transaction->index.line, transaction->index.way);
+ updateHighlighting(true, transaction);
+ } else {
+ updateHighlighting(false, nullptr);
+ }
}
QGraphicsSimpleTextItem* CacheGraphic::drawText(const QString& text, qreal x, qreal y) {

MODIFY
src/cachesim/cachegraphic.h
src/cachesim/cachegraphic.h
@@ -23,7 +23,7 @@ public slots:
* The cache simulator indicates that some entries in the cache has changed. CacheGraphic will, using @p
* transaction, lazily initialize and update all required values to reflect the new state of the cache.
*/
- void dataChanged(const CacheSim::CacheTransaction& transaction);
+ void dataChanged(const CacheSim::CacheTransaction* transaction);
/**
* @brief wayInvalidated

MODIFY
src/cachesim/cachesim.cpp
src/cachesim/cachesim.cpp
#include "processorhandler.h"
+#include <QApplication>
+#include <QThread>
#include <random>
#include <utility>
@@ -14,6 +16,7 @@ CacheSim::CacheSim(QObject* parent) : QObject(parent) {
connect(ProcessorHandler::get(), &ProcessorHandler::runFinished, this, [=] {
// Given that we are not updating the graphical state of the cache simulator whilst the processor is running,
// once running is finished, the entirety of the cache view should be reloaded in the graphical view.
+ emit hitrateChanged();
emit cacheInvalidated();
});
@@ -234,8 +237,11 @@ void CacheSim::pushAccessTrace(const CacheTransaction& transaction) {
const CacheAccessTrace& mostRecentTrace = m_accessTrace.rbegin()->second;
m_accessTrace[currentCycle] = CacheAccessTrace(mostRecentTrace, transaction.type, transaction.isHit, false);
}
+
+ if (!isAsynchronouslyAccessed()) {
emit hitrateChanged();
}
+}
void CacheSim::popAccessTrace() {
Q_ASSERT(m_accessTrace.size() > 0);
@@ -307,7 +313,15 @@ void CacheSim::access(uint32_t address, AccessType type) {
return;
}
- emit dataChanged(transaction);
+ if (isAsynchronouslyAccessed()) {
+ return;
+ }
+
+ emit dataChanged(&transaction);
+}
+
+bool CacheSim::isAsynchronouslyAccessed() const {
+ return QThread::currentThread() != QApplication::instance()->thread();
}
void CacheSim::undo() {
@@ -342,6 +356,14 @@ void CacheSim::undo() {
// Notify that changes to the way has been performed
emit wayInvalidated(lineIdx, wayIdx);
+
+ // Finally, re-emit the transaction which occurred in the previous cache access to update the cache
+ // highlighting state
+ if (m_traceStack.size() > 0) {
+ emit dataChanged(&m_traceStack.begin()->transaction);
+ } else {
+ emit dataChanged(nullptr);
+ }
}
CacheSim::CacheTrace CacheSim::popTrace() {
@@ -433,12 +455,14 @@ void CacheSim::processorWasReversed() {
return;
}
- if (m_accessTrace.rbegin()->first != ProcessorHandler::get()->getProcessor()->getCycleCount()) {
+ const unsigned cycleToUndo = ProcessorHandler::get()->getProcessor()->getCycleCount() + 1;
+ if (m_accessTrace.rbegin()->first != cycleToUndo) {
// No cache access in this cycle
return;
}
- volatile int a;
+ // It is now safe to undo the cycle at the top of our access stack(s).
+ undo();
}
void CacheSim::updateConfiguration() {

MODIFY
src/cachesim/cachesim.h
src/cachesim/cachesim.h
@@ -162,7 +162,7 @@ public slots:
signals:
void configurationChanged();
- void dataChanged(const CacheTransaction& transaction);
+ void dataChanged(const CacheTransaction* transaction);
void hitrateChanged();
// Signals that the entire cache line @p
@@ -191,6 +191,14 @@ private:
void updateConfiguration();
void pushAccessTrace(const CacheTransaction& transaction);
void popAccessTrace();
+ /**
+ * @brief isAsynchronouslyAccessed
+ * If the processor is in its 'running' state, it is currently being executed in a separate thread. In this case,
+ * cache accessing is also performed asynchronously, and we do not want to perform any signalling to the GUI (the
+ * entirety of the graphical representation of the cache is invalidated and redrawn upon asynchronous running
+ * finishing).
+ */
+ bool isAsynchronouslyAccessed() const;
/**
* @brief reassociateMemory

Integrate cache simulator with VSRTL processor cycle undoing