summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com>2025-03-08 21:07:09 -0500
committerGitHub <noreply@github.com>2025-03-08 21:07:09 -0500
commit0c6c9f8074aa5c356e2a1e582ab81355967a2060 (patch)
treee76871ceee74d36a660d5347c694493411426a7b
parent71ce62bd7797300c72b635a81ebcf677be4936a7 (diff)
parent7e64289d658d077ceffaa9f7272ccbe0f27277fa (diff)
Merge pull request #14 from bdunahu/bdunahuer
Storage.view + Dram.store methods, tests
-rw-r--r--inc/cache.h7
-rw-r--r--inc/definitions.h10
-rw-r--r--inc/dram.h7
-rw-r--r--inc/response.h8
-rw-r--r--inc/storage.h35
-rw-r--r--src/storage/cache.cc15
-rw-r--r--src/storage/dram.cc36
-rw-r--r--src/storage/storage.cc32
-rw-r--r--tests/cache.cc8
-rw-r--r--tests/dram.cc222
10 files changed, 338 insertions, 42 deletions
diff --git a/inc/cache.h b/inc/cache.h
index 101cd6e..f1fb942 100644
--- a/inc/cache.h
+++ b/inc/cache.h
@@ -8,7 +8,7 @@ class Cache : public Storage
/**
* Constructor.
* @param The number of `lines` contained in memory. The total number of
- * words is this number multiplied by 4.
+ * words is this number multiplied by LINE_SIZE.
* @param The next lowest level in storage. Methods from this object are
* called in case of a cache miss.
* @param The number of clock cycles each access takes.
@@ -17,9 +17,8 @@ class Cache : public Storage
Cache(int lines, Storage *lower, int delay);
~Cache();
- Response *write(Accessor accessor, signed int data, int address) override;
- Response *read(Accessor accessor, int address) override;
- int **view(int base, int lines) override;
+ Response write(Accessor accessor, signed int data, int address) override;
+ Response read(Accessor accessor, int address) override;
};
#endif /* CACHE_H_INCLUDED */
diff --git a/inc/definitions.h b/inc/definitions.h
new file mode 100644
index 0000000..1593162
--- /dev/null
+++ b/inc/definitions.h
@@ -0,0 +1,10 @@
+#ifndef DEFINITIONS_H
+#define DEFINITIONS_H
+
+/**
+ * Defines common macros.
+ */
+
+#define LINE_SIZE 4
+
+#endif /* DEFINITIONS_H_INCLUDED */
diff --git a/inc/dram.h b/inc/dram.h
index 41dd7de..cfac799 100644
--- a/inc/dram.h
+++ b/inc/dram.h
@@ -8,16 +8,15 @@ class Dram : public Storage
/**
* Constructor.
* @param The number of `lines` contained in memory. The total number of
- * words is this number multiplied by 4.
+ * words is this number multiplied by LINE_SIZE.
* @param The number of clock cycles each access takes.
* @return A new memory object.
*/
Dram(int lines, int delay);
~Dram();
- Response *write(Accessor accessor, signed int data, int address) override;
- Response *read(Accessor accessor, int address) override;
- int **view(int base, int lines) override;
+ Response write(Accessor accessor, signed int data, int address) override;
+ Response read(Accessor accessor, int address) override;
};
#endif /* DRAM_H_INCLUDED */
diff --git a/inc/response.h b/inc/response.h
index c8141fd..d945e0f 100644
--- a/inc/response.h
+++ b/inc/response.h
@@ -1,16 +1,10 @@
#ifndef RESPONSE_H
#define RESPONSE_H
-enum Status {
+enum Response {
OK,
WAIT,
BLOCKED,
};
-struct Response {
- Status status;
- int *line;
- int val;
-};
-
#endif /* RESPONSE_H_INCLUDED */
diff --git a/inc/storage.h b/inc/storage.h
index 1e512e2..4bf4591 100644
--- a/inc/storage.h
+++ b/inc/storage.h
@@ -1,13 +1,17 @@
#ifndef STORAGE_H
#define STORAGE_H
+#include "definitions.h"
#include "response.h"
+#include <algorithm>
#include <array>
#include <vector>
enum Accessor {
- MEMORY,
+ IDLE,
+ MEM,
FETCH,
L1CACHE,
+ SIDE,
};
class Storage
@@ -18,18 +22,17 @@ class Storage
* @param the source making the request.
* @param the data (hexadecimal) to write.
* @param the address to write to.
- * @return a status code reflecting the state of the storage level.
+ * @return a status code reflecting the state of the request.
*/
- virtual Response *
- write(Accessor accessor, signed int data, int address) = 0;
+ virtual Response write(Accessor accessor, signed int data, int address) = 0;
/**
* Get the data at `address`.
* @param the source making the request.
* @param the address being accessed.
- * @return a status code reflecting the state of the storage level, and the
+ * @return a status code reflecting the state of the request, and the
* data being returned.
*/
- virtual Response *read(Accessor accessor, int address) = 0;
+ virtual Response read(Accessor accessor, int address) = 0;
/**
* Sidedoor view of `lines` of memory starting at `base`.
* @param The base line to start getting memory from.
@@ -37,13 +40,21 @@ class Storage
* @return A matrix of data values, where each row is a line and each column
* is a word.
*/
- virtual int **view(int base, int lines) = 0;
+ std::vector<std::array<signed int, LINE_SIZE>> view(int base, int lines);
+ /**
+ * Advances to the next job if the current job is completed.
+ */
+ void resolve();
protected:
/**
+ * Helper for `write`.
+ */
+ void do_write(signed int, int);
+ /**
* The data currently stored in this level of storage.
*/
- std::vector<std::array<unsigned int, 4>> *data;
+ std::vector<std::array<signed int, LINE_SIZE>> *data;
/**
* A pointer to the next lowest level of storage.
* Used in case of cache misses.
@@ -54,6 +65,14 @@ class Storage
* requests.
*/
int delay;
+ /**
+ * The accessor currently being serviced.
+ */
+ enum Accessor requester;
+ /**
+ * The number of cycles until the current request is completed.
+ */
+ int wait_time;
};
#endif /* STORAGE_H_INCLUDED */
diff --git a/src/storage/cache.cc b/src/storage/cache.cc
index 34bdc5f..bbefb2a 100644
--- a/src/storage/cache.cc
+++ b/src/storage/cache.cc
@@ -1,8 +1,11 @@
-#include <cache.h>
+#include "cache.h"
+#include "definitions.h"
+#include "response.h"
+#include <bits/stdc++.h>
Cache::Cache(int lines, Storage *lower, int delay)
{
- this->data = new std::vector<std::array<unsigned int, 4>>;
+ this->data = new std::vector<std::array<signed int, LINE_SIZE>>;
this->data->resize(lines);
this->lower = lower;
this->delay = delay;
@@ -11,11 +14,9 @@ Cache::Cache(int lines, Storage *lower, int delay)
Cache::~Cache() { delete this->data; }
-Response *Cache::write(Accessor accessor, signed int data, int address)
+Response Cache::write(Accessor accessor, signed int data, int address)
{
- return new Response();
+ return WAIT;
}
-Response *Cache::read(Accessor accessor, int address) { return nullptr; }
-
-int **Cache::view(int base, int lines) { return nullptr; }
+Response Cache::read(Accessor accessor, int address) { return WAIT; }
diff --git a/src/storage/dram.cc b/src/storage/dram.cc
index 20858cd..7db5676 100644
--- a/src/storage/dram.cc
+++ b/src/storage/dram.cc
@@ -1,21 +1,41 @@
-#include <dram.h>
-#include <response.h>
+#include "dram.h"
+#include "definitions.h"
+#include "response.h"
+#include <algorithm>
Dram::Dram(int lines, int delay)
{
- this->data = new std::vector<std::array<unsigned int, 4>>;
+ this->data = new std::vector<std::array<signed int, LINE_SIZE>>;
this->data->resize(lines);
this->delay = delay;
+ this->wait_time = this->delay;
this->lower = nullptr;
+ this->requester = IDLE;
}
Dram::~Dram() { delete this->data; }
-Response *Dram::write(Accessor accessor, signed int data, int address)
+Response Dram::write(Accessor accessor, signed int data, int address)
{
- return new Response();
-}
+ Response r = WAIT;
+
+ if (accessor == SIDE) {
+ this->do_write(data, address);
+ r = OK;
+ } else {
+ /* Do this first--then process the first cycle immediately. */
+ if (this->requester == IDLE)
+ this->requester = accessor;
-Response *Dram::read(Accessor accessor, int address) { return nullptr; }
+ if (this->requester == accessor) {
+ if (this->wait_time == 0) {
+ this->do_write(data, address);
+ r = OK;
+ }
+ }
+ }
+
+ return r;
+}
-int **Dram::view(int base, int lines) { return nullptr; }
+Response Dram::read(Accessor accessor, int address) { return WAIT; }
diff --git a/src/storage/storage.cc b/src/storage/storage.cc
new file mode 100644
index 0000000..e3067a2
--- /dev/null
+++ b/src/storage/storage.cc
@@ -0,0 +1,32 @@
+#include "storage.h"
+#include "definitions.h"
+#include <algorithm>
+
+std::vector<std::array<signed int, LINE_SIZE>>
+Storage::view(int base, int lines)
+{
+ base = (base / LINE_SIZE) * LINE_SIZE;
+ std::vector<std::array<signed int, LINE_SIZE>> ret(lines + 1);
+ std::copy(
+ this->data->begin() + base, this->data->begin() + base + lines,
+ ret.begin());
+ return ret;
+}
+
+void Storage::do_write(signed data, int address)
+{
+ int line = address / LINE_SIZE;
+ int word = address % LINE_SIZE;
+
+ this->data->at(line).at(word) = data;
+}
+
+void Storage::resolve()
+{
+ if (this->wait_time == 0) {
+ this->requester = IDLE;
+ this->wait_time = delay;
+ } else if (this->requester != IDLE) {
+ --this->wait_time;
+ }
+}
diff --git a/tests/cache.cc b/tests/cache.cc
index 6580563..3c1fba6 100644
--- a/tests/cache.cc
+++ b/tests/cache.cc
@@ -1,8 +1,12 @@
#include "cache.h"
+#include "definitions.h"
#include <catch2/catch_test_macros.hpp>
-TEST_CASE("Constructor initialize test 1", "[cache]")
+TEST_CASE("Constructor singleton dram", "[cache]")
{
- Cache *c = new Cache(1, nullptr, 4);
+ Cache *c = new Cache(1, nullptr, LINE_SIZE);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
delete c;
}
diff --git a/tests/dram.cc b/tests/dram.cc
index 21182f8..c646135 100644
--- a/tests/dram.cc
+++ b/tests/dram.cc
@@ -1,8 +1,226 @@
#include "dram.h"
+#include "definitions.h"
+#include <array>
#include <catch2/catch_test_macros.hpp>
-TEST_CASE("Constructor initialize test 1", "[dram]")
+TEST_CASE("Construct singleton dram", "[dram]")
{
- Dram *d = new Dram(1, 4);
+ Dram *d = new Dram(1, 1);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0th element in zero cycles", "[dram]")
+{
+ Dram *d = new Dram(1, 0);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ signed int w = 0x11223344;
+
+ Response r = d->write(MEM, w, 0x00000000);
+ CHECK(r == OK);
+
+ expected.at(0) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0th element in three cycles", "[dram]")
+{
+ int delay = 3;
+ Dram *d = new Dram(1, delay);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ signed int w = 0x11223344;
+
+ int i;
+ Response r;
+ for (i = 0; i < delay; ++i) {
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == OK);
+ d->resolve();
+
+ expected.at(0) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0, 1th element in three cycles no "
+ "conflict",
+ "[dram]")
+{
+ int delay = 3;
+ Dram *d = new Dram(1, delay);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ signed int w = 0x11223344;
+
+ int i;
+ Response r;
+ for (i = 0; i < delay; ++i) {
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ CHECK(r == WAIT);
+
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(MEM, w, 0x00000000);
+ REQUIRE(r == OK);
+ // clock cycle did NOT resolve yet!
+ // this fetch should not make progress
+ r = d->write(FETCH, w, 0x00000001);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ CHECK(r == WAIT);
+ d->resolve();
+
+ expected.at(0) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ for (i = 0; i < delay; ++i) {
+ r = d->write(FETCH, w, 0x00000001);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(FETCH, w, 0x00000001);
+ actual = d->view(0, 1)[0];
+ CHECK(r == OK);
+
+ expected.at(1) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0, 1th element in three cycles much "
+ "conflict",
+ "[dram]")
+{
+ int delay = 2;
+ Dram *d = new Dram(1, 2);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ signed int w = 0x11223344;
+
+ int i;
+ Response r;
+ for (i = 0; i < delay; ++i) {
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == WAIT);
+
+ r = d->write(FETCH, w, 0x00000001);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == OK);
+ r = d->write(FETCH, w, 0x00000001);
+ CHECK(r == WAIT);
+ d->resolve();
+
+ actual = d->view(0, 1)[0];
+ expected.at(0) = w;
+ REQUIRE(expected == actual);
+
+ for (i = 0; i < delay; ++i) {
+ r = d->write(FETCH, w, 0x00000001);
+ CHECK(r == WAIT);
+
+ r = d->write(MEM, w, 0x00000003);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(FETCH, w, 0x00000001);
+ actual = d->view(0, 1)[0];
+ CHECK(r == OK);
+ r = d->write(MEM, w, 0x00000003);
+ CHECK(r == WAIT);
+
+ expected.at(1) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ delete d;
+}
+
+TEST_CASE("Sidedoor bypasses delay", "[dram]")
+{
+ int delay = 3;
+ Dram *d = new Dram(1, delay);
+ std::array<signed int, LINE_SIZE> expected = {0, 0, 0, 0};
+ std::array<signed int, LINE_SIZE> actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ signed int w = 0x11223344;
+
+ int i;
+ Response r;
+ for (i = 0; i < delay - 1; ++i) {
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == WAIT);
+
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ d->resolve();
+ }
+
+ r = d->write(MEM, w, 0x00000000);
+ CHECK(r == WAIT);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ r = d->write(SIDE, w, 0x00000001);
+ actual = d->view(0, 1)[0];
+ CHECK(r == OK);
+
+ expected.at(1) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
delete d;
}