Connect CacheSim accessing with VSRTL memory components
MODIFY
external/VSRTL
external/VSRTL
-Subproject commit 7b45b1fa4f5bd667202efb1655a047a4eaf8ecbb
+Subproject commit 6f33e49337f01fffbad78a83718c5222ac27fb37

MODIFY
src/cachesim/cachegraphic.cpp
src/cachesim/cachegraphic.cpp
@@ -28,6 +28,7 @@ CacheGraphic::CacheGraphic(CacheSim& cache) : QGraphicsObject(nullptr), m_cache(
connect(&cache, &CacheSim::configurationChanged, this, &CacheGraphic::cacheParametersChanged);
connect(&cache, &CacheSim::dataChanged, this, &CacheGraphic::dataChanged);
connect(&cache, &CacheSim::wayInvalidated, this, &CacheGraphic::wayInvalidated);
+ connect(&cache, &CacheSim::cacheInvalidated, this, &CacheGraphic::cacheInvalidated);
cacheParametersChanged();
}
@@ -160,6 +161,16 @@ std::unique_ptr<QGraphicsSimpleTextItem> CacheGraphic::createGraphicsTextItemSP(
return ptr;
}
+void CacheGraphic::cacheInvalidated() {
+ for (int lineIdx = 0; lineIdx < m_cache.getLines(); lineIdx++) {
+ 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);

MODIFY
src/cachesim/cachegraphic.h
src/cachesim/cachegraphic.h
@@ -32,6 +32,12 @@ public slots:
*/
void wayInvalidated(unsigned lineIdx, unsigned wayIdx);
+ /**
+ * @brief cacheInvalidated
+ * The cache simulator has signalled that the entirety of the cache simulator graphical view should be reloaded.
+ */
+ void cacheInvalidated();
+
/**
* @brief cacheParametersChanged
* Recalculates and redraws the graphic based on the current cache parameters

MODIFY
src/cachesim/cachesim.cpp
src/cachesim/cachesim.cpp
namespace Ripes {
CacheSim::CacheSim(QObject* parent) : QObject(parent) {
+ connect(ProcessorHandler::get(), &ProcessorHandler::reqProcessorReset, this, &CacheSim::processorReset);
+
+ 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 cacheInvalidated();
+ });
+
updateConfiguration();
}
@@ -19,12 +27,13 @@ void CacheSim::setType(CacheSim::CacheType type) {
void CacheSim::reassociateMemory() {
if (m_type == CacheType::DataCache) {
- m_memory = ProcessorHandler::get()->getDataMemory();
+ m_memory.rw = ProcessorHandler::get()->getDataMemory();
} else if (m_type == CacheType::InstrCache) {
- m_memory = ProcessorHandler::get()->getInstrMemory();
+ m_memory.rom = ProcessorHandler::get()->getInstrMemory();
} else {
Q_ASSERT(false);
}
+ Q_ASSERT(m_memory.rw != nullptr);
}
void CacheSim::updateCacheLineReplFields(CacheLine& line, unsigned wayIdx) {
@@ -214,11 +223,16 @@ void CacheSim::analyzeCacheAccess(CacheTransaction& transaction) const {
}
void CacheSim::pushAccessTrace(const CacheTransaction& transaction) {
+ // Access traces are pushed in sorted order into the access trace map; indexed by a key corresponding to the cycle
+ // of the acces.
+ const auto currentCycle = ProcessorHandler::get()->getProcessor()->getCycleCount();
if (m_accessTrace.size() == 0) {
- m_accessTrace[0] = CacheAccessTrace(transaction.isHit);
+ m_accessTrace[currentCycle] = CacheAccessTrace(transaction.isHit);
} else {
- m_accessTrace[m_accessTrace.size()] =
- CacheAccessTrace(m_accessTrace[m_accessTrace.size() - 1], transaction.type, transaction.isHit, false);
+ // The access trace should be constructed by the conjunction of the most-recent access trace + the access of the
+ // current cycle
+ const CacheAccessTrace& mostRecentTrace = m_accessTrace.rbegin()->second;
+ m_accessTrace[currentCycle] = CacheAccessTrace(mostRecentTrace, transaction.type, transaction.isHit, false);
}
emit hitrateChanged();
}
@@ -326,7 +340,7 @@ void CacheSim::undo() {
revertCacheLineReplFields(line, oldWay, wayIdx);
- // Notify that changes to teh way has been performed
+ // Notify that changes to the way has been performed
emit wayInvalidated(lineIdx, wayIdx);
}
@@ -378,8 +392,57 @@ const CacheSim::CacheLine* CacheSim::getLine(unsigned idx) const {
}
}
+void CacheSim::processorWasClocked() {
+ if (m_type == CacheType::DataCache) {
+ AccessType type;
+ // Determine whether the memory is being accessed in the current cycle, and if so, the access type.
+ switch (m_memory.rw->op.uValue()) {
+ case MemOp::SB:
+ case MemOp::SH:
+ case MemOp::SW:
+ if (m_memory.rw->wr_en.uValue() == 1) {
+ type = AccessType::Write;
+ break;
+ } else {
+ // Nothing to do
+ return;
+ }
+ case MemOp::LB:
+ case MemOp::LBU:
+ case MemOp::LH:
+ case MemOp::LHU:
+ case MemOp::LW:
+ type = AccessType::Read;
+ break;
+ case MemOp::NOP:
+ default:
+ // Nothing to do
+ return;
+ }
+
+ access(m_memory.rw->addr.uValue(), type);
+ } else {
+ // ROM; read in every cycle
+ access(m_memory.rom->addr.uValue(), AccessType::Read);
+ }
+}
+
+void CacheSim::processorWasReversed() {
+ if (m_accessTrace.size() == 0) {
+ // Nothing to reverse
+ return;
+ }
+
+ if (m_accessTrace.rbegin()->first != ProcessorHandler::get()->getProcessor()->getCycleCount()) {
+ // No cache access in this cycle
+ return;
+ }
+
+ volatile int a;
+}
+
void CacheSim::updateConfiguration() {
- // Cache configuration changes shall enforce a full reset of the computing system
+ // Cache configuration changed. Reset all state
m_cacheLines.clear();
m_accessTrace.clear();
m_traceStack.clear();
@@ -395,7 +458,26 @@ void CacheSim::updateConfiguration() {
m_tagMask = generateBitmask(32 - bitoffset) << bitoffset;
+ // Reset the graphical view
emit configurationChanged();
+
+ if (m_memory.rw || m_memory.rom) {
+ // Reload the initial (cycle 0) state of the processor. This is necessary to reflect ie. the instruction which
+ // is loaded from the instruction memory in cycle 0.
+ processorWasClocked();
+ }
+}
+
+void CacheSim::processorReset() {
+ // The processor might have changed. Since our signals/slot library cannot check for existing connection, we do the
+ // safe, slightly redundant, thing of disconnecting and reconnecting the VSRTL design update signals.
+ reassociateMemory();
+ auto* proc = ProcessorHandler::get()->getProcessorNonConst();
+ proc->designWasClocked.Connect(this, &CacheSim::processorWasClocked);
+ proc->designWasReversed.Connect(this, &CacheSim::processorWasReversed);
+ proc->designWasReset.Connect(this, &CacheSim::updateConfiguration);
+
+ updateConfiguration();
}
void CacheSim::setBlocks(unsigned blocks) {

MODIFY
src/cachesim/cachesim.h
src/cachesim/cachesim.h
#include "../external/VSRTL/core/vsrtl_register.h"
#include "processors/RISC-V/rv_memory.h"
-using RVMemory = vsrtl::core::RVMemory<32, 32>;
+using RWMemory = vsrtl::core::RVMemory<32, 32>;
+using ROMMemory = vsrtl::core::ROM<32, 32>;
namespace Ripes {
@@ -113,7 +114,7 @@ public:
void access(uint32_t address, AccessType type);
void undo();
- void reset();
+ void processorReset();
WriteAllocPolicy getWriteAllocPolicy() const { return m_wrAllocPolicy; }
ReplPolicy getReplacementPolicy() const { return m_replPolicy; }
@@ -152,12 +153,32 @@ public slots:
void setWays(unsigned ways);
void setPreset(const CachePreset& preset);
+ /**
+ * @brief processorWasClocked/processorWasReversed
+ * Slot functions for clocked/Reversed signals emitted by the currently attached processor.
+ */
+ void processorWasClocked();
+ void processorWasReversed();
+
signals:
void configurationChanged();
void dataChanged(const CacheTransaction& transaction);
- void wayInvalidated(unsigned lineIdx, unsigned wayIdx);
void hitrateChanged();
+ // Signals that the entire cache line @p
+ /**
+ * @brief wayInvalidated
+ * Signals that all ways in the cacheline @param lineIdx which contains way @param wayIdx should be invalidated in
+ * the graphical view.
+ */
+ void wayInvalidated(unsigned lineIdx, unsigned wayIdx);
+
+ /**
+ * @brief cacheInvalidated
+ * Signals that all cachelines in the cache should be invalidated in the graphical view
+ */
+ void cacheInvalidated();
+
private:
struct CacheTrace {
CacheTransaction transaction;
@@ -189,8 +210,17 @@ private:
int m_lines = 2; // Some power of 2
int m_ways = 2; // Some power of 2
+ /**
+ * @brief m_memory
+ * The cache simulator may be attached to either a ROM or a Read/Write memory element. Accessing the underlying
+ * VSRTL component signals are dependent on the given type of the memory.
+ */
CacheType m_type;
- RVMemory const* m_memory = nullptr;
+ union {
+ RWMemory const* rw = nullptr;
+ ROMMemory const* rom;
+
+ } m_memory;
/**
* @brief m_cacheLines

MODIFY
src/processorhandler.cpp
src/processorhandler.cpp
@@ -57,8 +57,8 @@ const vsrtl::core::SparseArray& ProcessorHandler::getMemory() const {
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::ROM<RV_REG_WIDTH, RV_INSTR_WIDTH>* ProcessorHandler::getInstrMemory() const {
+ return dynamic_cast<const vsrtl::core::ROM<RV_REG_WIDTH, RV_INSTR_WIDTH>*>(m_currentProcessor->getInstrMemory());
}
const vsrtl::core::SparseArray& ProcessorHandler::getRegisters() const {

MODIFY
src/processorhandler.h
src/processorhandler.h
@@ -84,7 +84,7 @@ 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;
+ const vsrtl::core::ROM<RV_REG_WIDTH, RV_INSTR_WIDTH>* getInstrMemory() const;
/**
* @brief setRegisterValue

Connect CacheSim accessing with VSRTL memory components