Work on creating cache level hierarchy
MODIFY
RISC-V-sim.pro
RISC-V-sim.pro
QT += widgets
+CONFIG += c++14
+
INCLUDEPATH += $$PWD/src/
SOURCES += src/main.cpp \
src/parser.cpp \
src/runner.cpp \
- src/cache.cpp \
src/dmcache.cpp \
src/facache.cpp \
src/mainwindow.cpp \
@@ -14,13 +15,14 @@ SOURCES += src/main.cpp \
src/processortab.cpp \
src/memorytab.cpp \
src/cachetab.cpp \
- src/cachesetupwidget.cpp
+ src/cachesetupwidget.cpp \
+ src/cachebase.cpp \
+ src/runnercache.cpp
HEADERS += \
src/parser.h \
src/defines.h \
src/runner.h \
- src/cache.h \
src/dmcache.h \
src/facache.h \
src/mainwindow.h \
@@ -29,7 +31,9 @@ HEADERS += \
src/processortab.h \
src/memorytab.h \
src/cachetab.h \
- src/cachesetupwidget.h
+ src/cachesetupwidget.h \
+ src/cachebase.h \
+ src/runnercache.h
FORMS += \
src/mainwindow.ui \

DELETE
src/cache.cpp
-#include "cache.h"
-#include <assert.h>
-
-Cache::Cache(int *cycleCounterPtr, int missPenalty, int searchPenalty) {
- // Initialize cache of size, set to zeros
- m_missPenalty = missPenalty;
- m_searchPenalty = searchPenalty;
- m_cycleCounterPtr = cycleCounterPtr;
-}
-
-void Cache::assertSize(int size) const {
- // Assert cache size is a power of 2
- assert((size & (size - 1)) == 0);
-}

DELETE
src/cache.h
-#ifndef CACHE_H
-#define CACHE_H
-
-#include <cstdint>
-#include <vector>
-
-class Cache {
-public:
- Cache(int *cycleCounterPtr, int missPenalty = 0, int searchPenalty = 0);
- virtual uint32_t readData(uint32_t address) = 0;
- virtual void writeData(uint32_t address) = 0;
-
- void setMissPenalty(int cycles) { m_missPenalty = cycles; }
- void setSearchPenalty(int cycles) { m_searchPenalty = cycles; }
-
- virtual void resize(int size) = 0;
-
-protected:
- void assertSize(int size) const;
-
- int m_readCount = 0;
- int m_missCount = 0;
-
- int m_missPenalty;
- int m_searchPenalty;
- int m_memoryPenalty;
-
- uint32_t *m_memoryPtr;
- int *m_cycleCounterPtr; // pointer to Runner's cycle counter
- Cache *m_childCache = nullptr; // pointer to child cache (ie. L1 -> L2)
-};
-
-#endif // CACHE_H

ADD
src/cachebase.cpp
+#include "cachebase.h"
+#include <assert.h>
+
+CacheBase::CacheBase(CacheProperties properties, int *cycleCounterPtr) {
+ // Initialize cache of size, set to zeros
+ m_properties = properties;
+}
+
+void CacheBase::assertSize(int size) const {
+ // Assert cache size is a power of 2
+ assert((size & (size - 1)) == 0);
+}

ADD
src/cachebase.h
+#ifndef CACHE_H
+#define CACHE_H
+
+#include "defines.h"
+
+#include <cstdint>
+#include <vector>
+
+typedef struct {
+ int readCount = 0;
+ int missCount = 0;
+
+ int missPenalty;
+ int searchPenalty;
+ int memoryPenalty;
+ cacheType type;
+
+ int size;
+} CacheProperties;
+
+// Base class for all cache types
+
+class CacheBase {
+public:
+ CacheBase(CacheProperties properties, int *cycleCounterPtr);
+ virtual uint32_t readData(uint32_t address) = 0;
+ virtual void writeData(uint32_t address) = 0;
+
+ void setMissPenalty(int cycles) { m_properties.missPenalty = cycles; }
+ void setSearchPenalty(int cycles) { m_properties.searchPenalty = cycles; }
+ void setChildCache(CacheBase *childCache) { m_childCache = childCache; }
+ virtual void resize(int size) = 0;
+
+protected:
+ void assertSize(int size) const;
+
+ CacheProperties m_properties;
+
+ uint32_t *m_memoryPtr;
+ int *m_cycleCounterPtr; // pointer to Runner's cycle counter
+ CacheBase *m_childCache = nullptr; // pointer to child cache (ie. L1 -> L2)
+};
+
+#endif // CACHE_H

MODIFY
src/defines.h
src/defines.h
@@ -18,6 +18,9 @@ enum instrType {
INVALID = 0b0
};
+enum cacheLevel { L1, L2, L3 };
+enum cacheType { DM, SA, FA };
+
typedef std::vector<uint8_t> memory;
enum instrState {

MODIFY
src/dmcache.cpp
src/dmcache.cpp
#include "dmcache.h"
-DMCache::DMCache(int size, int *cycleCounterPtr) : Cache(cycleCounterPtr) {
- assertSize(size);
+DMCache::DMCache(CacheProperties properties, int *cycleCounterPtr)
+ : CacheBase(properties, cycleCounterPtr) {
+ assertSize(m_properties.size);
// Initialize cache to all zeros and invalidated
- for (auto i = 0; i < size; i++) {
+ for (auto i = 0; i < m_properties.size; i++) {
// Initialize cache line to 0, and invalid
m_cache[i] = std::pair<bool, uint32_t>(false, 0);
}
}
uint32_t DMCache::readData(uint32_t address) {
- m_readCount++;
+ m_properties.readCount++;
auto it = m_cache.find(address);
if (it != m_cache.end() && it->second.first) {
@@ -19,25 +20,27 @@ uint32_t DMCache::readData(uint32_t address) {
return it->second.second;
} else {
// Cache miss
- m_missCount++;
- *m_cycleCounterPtr += m_missPenalty;
- if (m_childCache != nullptr) {
+ m_properties.missCount++;
+ *m_cycleCounterPtr += m_properties.missPenalty;
+ if (m_childCache) {
// Cache has subcache, delegate memory request to subcache
return m_childCache->readData(address);
} else {
// No subcaches available, read straight from memory
- *m_cycleCounterPtr += m_memoryPenalty;
+ *m_cycleCounterPtr += m_properties.memoryPenalty;
// @TODO : return an actual memory value here!
return 0;
}
}
}
+void DMCache::resize(int size) {}
+
void DMCache::writeData(uint32_t address) {}
void DMCache::searchCache(uint32_t address) const {}
-void Cache::resize(int size) {
+void CacheBase::resize(int size) {
assertSize(size);
// do resize...
}

MODIFY
src/dmcache.h
src/dmcache.h
#ifndef DMCACHE_H
#define DMCACHE_H
-#include "cache.h"
+#include "cachebase.h"
#include <cstdint>
#include <map>
// Direct mapped cache
-class DMCache : public Cache {
+class DMCache : public CacheBase {
public:
- DMCache(int size, int *cycleCounterPtr);
+ DMCache(CacheProperties properties, int *cycleCounterPtr = nullptr);
uint32_t readData(uint32_t address) override;
void writeData(uint32_t address) override;
+ void resize(int size) override;
private:
void searchCache(uint32_t address) const;

MODIFY
src/facache.cpp
src/facache.cpp
#include "facache.h"
-FACache::FACache(int size, int *cycleCounterPtr) : Cache(cycleCounterPtr) {}
+FACache::FACache(CacheProperties properties, int *cycleCounterPtr)
+ : CacheBase(properties, cycleCounterPtr) {}
uint32_t FACache::readData(uint32_t address) {
- m_readCount++;
+ m_properties.readCount++;
return 0;
}
void FACache::writeData(uint32_t address) {}
+void FACache::resize(int size) {}
+
void FACache::searchCache(uint32_t address) const {}

MODIFY
src/facache.h
src/facache.h
#ifndef FACACHE_H
#define FACACHE_H
-#include "cache.h"
+#include "cachebase.h"
// Fully associative cache
-class FACache : public Cache {
+
+class FACache : public CacheBase {
public:
- FACache(int size, int *cycleCounterPtr);
+ FACache(CacheProperties properties, int *cycleCounterPtr = nullptr);
uint32_t readData(uint32_t address) override;
void writeData(uint32_t address) override;
+ void resize(int size) override;
private:
void searchCache(uint32_t address) const;

MODIFY
src/main.cpp
src/main.cpp
#include "parser.h"
#include "runner.h"
+#include "QDebug"
+
using namespace std;
int main(int argc, char **argv) {
@@ -13,8 +15,6 @@ int main(int argc, char **argv) {
return 1;
}
- uint8_t a[4] = {1, 2, 3, 4};
-
Parser parser;
// For now, initialize parser with input argument
if (parser.init(argv[1])) {

ADD
src/runnercache.cpp
+#include "runnercache.h"
+
+#include "dmcache.h"
+#include "facache.h"
+
+RunnerCache::RunnerCache() {}
+
+uint32_t RunnerCache::readData(uint32_t address) { return 0; }
+
+void RunnerCache::writeData(uint32_t address) {}
+
+void RunnerCache::createCacheLevel(cacheLevel level,
+ CacheProperties properties) {
+ // Creates a cache at the requested cache level with the given properties,
+ // and sets the newly created cache as a childCache of a potential parent
+ switch (level) {
+ case L1:
+ m_L1 = createCache(properties);
+ break;
+ case L2:
+ m_L2 = createCache(properties);
+ m_L1->setChildCache(m_L2.get());
+ break;
+ case L3:
+ m_L3 = createCache(properties);
+ m_L2->setChildCache(m_L3.get());
+ break;
+ }
+}
+
+std::unique_ptr<CacheBase>
+RunnerCache::createCache(CacheProperties properties) {
+ switch (properties.type) {
+ case DM:
+ return std::make_unique<DMCache>(properties);
+ case SA:
+ // return std::make_unique<>(properties);
+ case FA:
+ return std::make_unique<FACache>(properties);
+ }
+}
+
+void RunnerCache::deleteCache(cacheLevel level) {
+ switch (level) {
+ case L1:
+ m_L1.reset();
+ break;
+ case L2:
+ m_L2.reset();
+ break;
+ case L3:
+ m_L3.reset();
+ break;
+ }
+}

ADD
src/runnercache.h
+#ifndef RUNNERCACHE_H
+#define RUNNERCACHE_H
+
+#include "cachebase.h"
+#include <memory>
+
+// Class for handling cache fetching and structuring, for the runner
+
+class RunnerCache {
+public:
+ RunnerCache();
+
+public:
+ void createCacheLevel(cacheLevel level, CacheProperties properties);
+ void deleteCache(cacheLevel level);
+ void modifyCache(cacheLevel level, CacheProperties properties);
+
+ uint32_t readData(uint32_t address);
+ void writeData(uint32_t address);
+
+private:
+ std::unique_ptr<CacheBase> createCache(CacheProperties properties);
+ std::unique_ptr<CacheBase> m_L1;
+ std::unique_ptr<CacheBase> m_L2;
+ std::unique_ptr<CacheBase> m_L3;
+};
+
+#endif // RUNNERCACHE_H

Work on creating cache level hierarchy