Expose data and instruction memory components through RipesProcessor interface
MODIFY
src/cachesim/cachesim.cpp
src/cachesim/cachesim.cpp
#include "cachesim.h"
#include "binutils.h"
+#include "processorhandler.h"
+
#include <random>
#include <utility>
@@ -10,6 +12,21 @@ CacheSim::CacheSim(QObject* parent) : QObject(parent) {
updateConfiguration();
}
+void CacheSim::setType(CacheSim::CacheType type) {
+ m_type = type;
+ reassociateMemory();
+}
+
+void CacheSim::reassociateMemory() {
+ if (m_type == CacheType::DataCache) {
+ m_memory = ProcessorHandler::get()->getDataMemory();
+ } else if (m_type == CacheType::InstrCache) {
+ m_memory = ProcessorHandler::get()->getInstrMemory();
+ } else {
+ Q_ASSERT(false);
+ }
+}
+
void CacheSim::updateCacheLineReplFields(CacheLine& line, unsigned wayIdx) {
if (getReplacementPolicy() == ReplPolicy::LRU) {
// Find previous LRU value for the updated index

MODIFY
src/cachesim/cachesim.h
src/cachesim/cachesim.h
#include <QObject>
#include "../external/VSRTL/core/vsrtl_register.h"
+#include "processors/RISC-V/rv_memory.h"
+
+using RVMemory = vsrtl::core::RVMemory<32, 32>;
namespace Ripes {
@@ -19,6 +22,7 @@ public:
enum class WritePolicy { WriteThrough, WriteBack };
enum class ReplPolicy { Random, LRU };
enum class AccessType { Read, Write };
+ enum class CacheType { DataCache, InstrCache };
struct CacheSize {
unsigned bits = 0;
@@ -90,6 +94,7 @@ public:
using CacheLine = std::map<unsigned, CacheWay>;
CacheSim(QObject* parent);
+ void setType(CacheType type);
void setWritePolicy(WritePolicy policy) {
m_wrPolicy = policy;
@@ -166,6 +171,12 @@ private:
void pushAccessTrace(const CacheTransaction& transaction);
void popAccessTrace();
+ /**
+ * @brief reassociateMemory
+ * Binds to a memory component exposed by the processor handler, based on the current cache type.
+ */
+ void reassociateMemory();
+
ReplPolicy m_replPolicy = ReplPolicy::LRU;
WritePolicy m_wrPolicy = WritePolicy::WriteBack;
WriteAllocPolicy m_wrAllocPolicy = WriteAllocPolicy::WriteAllocate;
@@ -178,6 +189,9 @@ private:
int m_lines = 2; // Some power of 2
int m_ways = 2; // Some power of 2
+ CacheType m_type;
+ RVMemory const* m_memory = nullptr;
+
/**
* @brief m_cacheLines
* The datastructure for storing our cache hierachy, as per the current cache configuration.

MODIFY
src/cachesim/cachewidget.cpp
src/cachesim/cachewidget.cpp
#include <QGraphicsView>
#include "cachegraphic.h"
-#include "cachesim.h"
namespace Ripes {
@@ -13,14 +12,18 @@ CacheWidget::CacheWidget(QWidget* parent) : QWidget(parent), m_ui(new Ui::CacheW
m_ui->setupUi(this);
auto* scene = new QGraphicsScene(this);
- auto* cacheSim = new CacheSim(this);
- m_ui->cacheConfig->setCache(cacheSim);
+ m_cacheSim = new CacheSim(this);
+ m_ui->cacheConfig->setCache(m_cacheSim);
- auto* cacheGraphic = new CacheGraphic(*cacheSim);
+ auto* cacheGraphic = new CacheGraphic(*m_cacheSim);
m_ui->cacheView->setScene(scene);
scene->addItem(cacheGraphic);
}
+void CacheWidget::setType(CacheSim::CacheType type) {
+ m_cacheSim->setType(type);
+}
+
CacheWidget::~CacheWidget() {
delete m_ui;
}

MODIFY
src/cachesim/cachewidget.h
src/cachesim/cachewidget.h
#pragma once
#include <QWidget>
+#include "cachesim.h"
+#include "processors/RISC-V/rv_memory.h"
+
+using RVMemory = vsrtl::core::RVMemory<32, 32>;
namespace Ripes {
+class CacheSim;
+
namespace Ui {
class CacheWidget;
}
@@ -15,8 +21,11 @@ public:
explicit CacheWidget(QWidget* parent = nullptr);
~CacheWidget();
+ void setType(CacheSim::CacheType type);
+
private:
Ui::CacheWidget* m_ui;
+ CacheSim* m_cacheSim = nullptr;
};
} // namespace Ripes

MODIFY
src/memorytab.cpp
src/memorytab.cpp
#include <QGraphicsItem>
#include <QToolBar>
+#include "cachesim/cachesim.h"
+
namespace Ripes {
MemoryTab::MemoryTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, parent), m_ui(new Ui::MemoryTab) {
@@ -11,6 +13,9 @@ MemoryTab::MemoryTab(QToolBar* toolbar, QWidget* parent) : RipesTab(toolbar, par
m_ui->memoryViewerWidget->updateModel();
m_ui->memoryViewerWidget->updateView();
+
+ m_ui->dataCache->setType(CacheSim::CacheType::DataCache);
+ m_ui->instructionCache->setType(CacheSim::CacheType::InstrCache);
}
void MemoryTab::update() {

MODIFY
src/memorytab.ui
src/memorytab.ui
</widget>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
- <number>1</number>
+ <number>0</number>
</property>
<widget class="QWidget" name="tab_3">
<attribute name="title">

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -54,6 +54,13 @@ const vsrtl::core::SparseArray& ProcessorHandler::getMemory() const {
return m_currentProcessor->getMemory();
}
+const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>* ProcessorHandler::getDataMemory() const {
+ return dynamic_cast<const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>*>(m_currentProcessor->getDataMemory());
+}
+const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>* ProcessorHandler::getInstrMemory() const {
+ return dynamic_cast<const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>*>(m_currentProcessor->getInstrMemory());
+}
+
const vsrtl::core::SparseArray& ProcessorHandler::getRegisters() const {
return m_currentProcessor->getArchRegisters();
}

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -83,6 +83,8 @@ public:
*/
const vsrtl::core::SparseArray& getMemory() const;
const vsrtl::core::SparseArray& getRegisters() const;
+ const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>* getDataMemory() const;
+ const vsrtl::core::RVMemory<RV_REG_WIDTH, RV_REG_WIDTH>* getInstrMemory() const;
/**
* @brief setRegisterValue

MODIFY
src/processors/RISC-V/rv5s/rv5s.h
src/processors/RISC-V/rv5s/rv5s.h
@@ -424,6 +424,9 @@ public:
ecallChecker->setSysCallExiting(ecallChecker->isSysCallExiting() || fr.exitSyscall);
}
+ const Component* getDataMemory() const override { return data_mem; }
+ const Component* getInstrMemory() const override { return instr_mem; }
+
bool finished() const override {
// The processor is finished when there are no more valid instructions in the pipeline
bool allStagesInvalid = true;

MODIFY
src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h
src/processors/RISC-V/rv5s_no_fw_hz/rv5s_no_fw_hz.h
@@ -350,6 +350,9 @@ public:
ecallChecker->setSysCallExiting(ecallChecker->isSysCallExiting() || fr.exitSyscall);
}
+ const Component* getDataMemory() const override { return data_mem; }
+ const Component* getInstrMemory() const override { return instr_mem; }
+
bool finished() const override {
// The processor is finished when there are no more valid instructions in the pipeline
bool allStagesInvalid = true;

MODIFY
src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h
src/processors/RISC-V/rv5s_no_hz/rv5s_no_hz.h
@@ -384,6 +384,9 @@ public:
ecallChecker->setSysCallExiting(ecallChecker->isSysCallExiting() || fr.exitSyscall);
}
+ const Component* getDataMemory() const override { return data_mem; }
+ const Component* getInstrMemory() const override { return instr_mem; }
+
bool finished() const override {
// The processor is finished when there are no more valid instructions in the pipeline
bool allStagesInvalid = true;

MODIFY
src/processors/RISC-V/rvss/rvss.h
src/processors/RISC-V/rvss/rvss.h
@@ -169,6 +169,9 @@ public:
}
bool finished() const override { return m_finished; }
+ const Component* getDataMemory() const override { return data_mem; }
+ const Component* getInstrMemory() const override { return instr_mem; }
+
void setRegister(unsigned i, uint32_t v) override { setSynchronousValue(registerFile->_wr_mem, i, v); }
void clock() override {

MODIFY
src/processors/ripesprocessor.h
src/processors/ripesprocessor.h
@@ -98,6 +98,14 @@ public:
*/
virtual SparseArray& getMemory() = 0;
+ /**
+ * @brief getData/InstrMemory
+ * @returns a pointer to the component which implements the instruction and data memory interfaces. These types may
+ * be implementation specific, and as such should be cast to these types at the callers end.
+ */
+ virtual const Component* getDataMemory() const = 0;
+ virtual const Component* getInstrMemory() const = 0;
+
/**
* @brief getRegister
* @return value currently present in register @p i

Expose data and instruction memory components through RipesProcessor interface