summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rw-r--r--inc/cache.h26
-rw-r--r--src/cache.cc70
3 files changed, 71 insertions, 29 deletions
diff --git a/README.md b/README.md
index dfde60f..ad0f4fb 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,6 @@
# RAM - RAM Acts Magically
-##
-
-This is a cache and memory simulator for a custom ISA nicknamed "RISC V[ECTOR]". It uses a writeback and write allocate on a miss scheme, and supports a configurable number of cache levels and ways, with a least-recently used replacement policy.
+This is a cache and memory simulator for a custom ISA nicknamed "RISC V[ECTOR]". It uses a writeback and write allocate on a miss scheme. It also supports a configurable number of cache levels and ways (allowing creation of a direct mapped or fully associative cache). Additionally, it uses a least-recently used replacement policy.
## Dependencies
diff --git a/inc/cache.h b/inc/cache.h
index 6f06466..8075d1a 100644
--- a/inc/cache.h
+++ b/inc/cache.h
@@ -55,7 +55,31 @@ nn * Constructor.
* @param the address that must be present in cache.
* @param 0 if the address is currently in cache, 1 if it is being fetched.
*/
- int is_address_missing(int address);
+ int priming_address(int address);
+ /**
+ * Walks the ways in this set of ways. If none of the tags match, returns -1. Otherwise, returns
+ * the index the matching data is located.
+ * @param an index aligned to the set of ways in `this->data'
+ * @param the tag to be matched
+ * @return -1 if the tag is not present in this set of ways (not in cache), or the true index if
+ * the tag is present.
+ */
+ int is_address_missing(int true_index, int tag);
+ /**
+ * Converts an index into a set of ways into an index into `this->data', which is a
+ * 1D array. The next `this->ways' entries after the returned index represent the ways in the
+ * set for this index.
+ * @param an index to a set of ways
+ * @param an index aligned to the set of ways in `this->data'
+ */
+ int get_true_index(int index);
+ /**
+ * Selects an index into the `data' and `meta' tables for write back using a random replacement
+ * policy.
+ * @param an index aligned to the set of ways in `this->data'
+ * @return an index aligned to the data line selected for eviction
+ */
+ int get_replacement_index(int index);
/**
* The number of bits required to specify a line in this level of cache.
*/
diff --git a/src/cache.cc b/src/cache.cc
index 08545fd..a2d4525 100644
--- a/src/cache.cc
+++ b/src/cache.cc
@@ -1,5 +1,6 @@
#include "cache.h"
#include "definitions.h"
+#include <cstdlib>
#include <iostream>
#include <iterator>
@@ -61,53 +62,72 @@ Cache::read_word(void *id, int address, signed int &data)
int
Cache::process(void *id, int address, std::function<void(int index, int offset)> request_handler)
{
- if (!preprocess(id) || is_address_missing(address) || !this->is_data_ready())
+ if (!preprocess(id) || priming_address(address) || !this->is_data_ready())
return 0;
int tag, index, offset;
GET_FIELDS(address, &tag, &index, &offset);
+ index = this->get_true_index(index);
request_handler(index, offset);
return 1;
}
int
-Cache::is_address_missing(int expected)
+Cache::priming_address(int address)
{
- int r, q, tag, index, offset;
- std::array<signed int, LINE_SIZE> *actual;
+ int tag, index, offset;
+ int r1, r2;
+ std::array<signed int, LINE_SIZE> *evict;
std::array<int, 3> *meta;
- GET_FIELDS(expected, &tag, &index, &offset);
- r = 0;
- meta = &this->meta.at(index);
- actual = &this->data->at(index);
+ r1 = 0;
+ GET_FIELDS(address, &tag, &index, &offset);
+ index = this->get_true_index(index);
+
+ if (this->is_address_missing(index, tag)) {
+ r1 = 1;
+
+ index = this->get_replacement_index(index);
+ meta = &this->meta.at(index);
+ evict = &this->data->at(index);
- if (meta->at(0) != tag) {
- r = 1;
+ // handle eviction of dirty cache lines
if (meta->at(1) >= 0) {
- q = this->lower->write_line(
- this, *actual, ((index << LINE_SPEC) + (meta->at(0) << (this->size + LINE_SPEC))));
- if (q) {
+ r2 = this->lower->write_line(
+ this, *evict, ((index << LINE_SPEC) + (meta->at(0) << (this->size + LINE_SPEC))));
+ if (r2)
meta->at(1) = -1;
- }
} else {
- q = this->lower->read_line(this, expected, *actual);
- if (q) {
+ r2 = this->lower->read_line(this, address, *evict);
+ if (r2) {
meta->at(0) = tag;
}
}
}
- return r;
+ return r1;
+}
+
+int
+Cache::is_address_missing(int index, int tag)
+{
+ int i;
+
+ for (i = 0; i < (1 << this->ways); ++i)
+ if (this->meta.at(index + i).at(0) == tag)
+ return i;
+ return -1;
}
-// unsigned int
-// Cache::get_true_index(unsigned int index)
-// {
-// }
+int
+Cache::get_true_index(int index)
+{
+ return index * (1 << this->ways);
+}
-// unsigned int
-// Cache::get_replacement_index(unsigned int index)
-// {
-// }
+int
+Cache::get_replacement_index(int index)
+{
+ return index + (rand() % (1 << this->ways));
+}