summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-06 01:15:31 -0500
committerbd <bdunahu@operationnull.com>2025-03-06 01:15:31 -0500
commitc38c0858ad4c9158a8d4361069309a9f0ff3aed8 (patch)
treeaa84162d707090a4ca2c741ff2e6e9799bc612c9
parent3322aa0845f7fe9cc98aa4e429bd5ecf72a5c27e (diff)
dram implement delay and conflicting request logic
-rw-r--r--inc/storage.h10
-rw-r--r--src/storage/dram.cc24
-rw-r--r--tests/dram.cc204
3 files changed, 232 insertions, 6 deletions
diff --git a/inc/storage.h b/inc/storage.h
index c0f09a3..f5659c5 100644
--- a/inc/storage.h
+++ b/inc/storage.h
@@ -3,12 +3,14 @@
#include "definitions.h"
#include "response.h"
#include <array>
+#include <unordered_map>
#include <vector>
enum Accessor {
MEMORY,
FETCH,
L1CACHE,
+ IDLE,
};
class Storage
@@ -55,6 +57,14 @@ class Storage
* requests.
*/
int delay;
+ /**
+ * The accessor currently being serviced.
+ */
+ enum Accessor servicing;
+ /**
+ * The number of cycles until the currently request is completed.
+ */
+ int wait_time;
};
#endif /* STORAGE_H_INCLUDED */
diff --git a/src/storage/dram.cc b/src/storage/dram.cc
index 845db21..3143a61 100644
--- a/src/storage/dram.cc
+++ b/src/storage/dram.cc
@@ -9,6 +9,7 @@ Dram::Dram(int lines, int delay)
this->data->resize(lines);
this->delay = delay;
this->lower = nullptr;
+ this->servicing = IDLE;
}
Dram::~Dram() { delete this->data; }
@@ -16,12 +17,27 @@ Dram::~Dram() { delete this->data; }
Response *Dram::write(Accessor accessor, signed int data, int address)
{
struct Response *r = new Response();
- int line = address / LINE_SIZE;
- int word = address % LINE_SIZE;
+ r->status = WAIT;
- this->data->at(line).at(word) = data;
+ /* Do this first--then process the first cycle immediately. */
+ if (this->servicing == IDLE) {
+ this->servicing = accessor;
+ this->wait_time = delay;
+ }
+
+ if (this->servicing == accessor) {
+ if (this->wait_time == 0) {
+ int line = address / LINE_SIZE;
+ int word = address % LINE_SIZE;
+
+ this->servicing = IDLE;
+ this->data->at(line).at(word) = data;
+ r->status = OK;
+ } else {
+ --this->wait_time;
+ }
+ }
- r->status = OK;
return r;
}
diff --git a/tests/dram.cc b/tests/dram.cc
index 15e2990..be69263 100644
--- a/tests/dram.cc
+++ b/tests/dram.cc
@@ -1,7 +1,7 @@
#include "dram.h"
#include "definitions.h"
-#include <catch2/catch_test_macros.hpp>
#include <array>
+#include <catch2/catch_test_macros.hpp>
TEST_CASE("Construct singleton dram", "[dram]")
{
@@ -12,7 +12,8 @@ TEST_CASE("Construct singleton dram", "[dram]")
delete d;
}
-TEST_CASE("Construct ingleton dram, store 0th element in zero cycles", "[dram]")
+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};
@@ -24,11 +25,210 @@ TEST_CASE("Construct ingleton dram, store 0th element in zero cycles", "[dram]")
Response *r = d->write(MEMORY, w, 0x00000000);
REQUIRE(r->status == OK);
+ expected.at(0) = w;
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ delete r;
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0th element in three cycles", "[dram]")
+{
+ Dram *d = new Dram(1, 3);
+ 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;
+
+ // MEMORY CYCLE 1
+ Response *r = d->write(MEMORY, w, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+
+ // MEMORY CYCLE 2
+ r = d->write(MEMORY, w, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // MEMORY CYCLE 3
+ r = d->write(MEMORY, w, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // MEMORY CYCLE 4
+ r = d->write(MEMORY, w, 0x00000000);
+ REQUIRE(r->status == OK);
+ delete r;
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]")
+{
+ Dram *d = new Dram(1, 3);
+ 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 w1 = 0x11223344;
+ signed int w2 = 0x55667788;
+
+ // MEMORY CYCLE 1
+ Response *r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // MEMORY CYCLE 2
+ actual = d->view(0, 1)[0];
+ r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
delete r;
+
+ // MEMORY CYCLE 3
+ r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // MEMORY CYCLE 4
+ r = d->write(MEMORY, w1, 0x00000000);
+ REQUIRE(r->status == OK);
+ delete r;
+ // NOTE: servicing on the same clock cycle should probably not be allowed
+ // FETCH CYCLE 1
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ expected.at(0) = w1;
+ actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ // FETCH CYCLE 2
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // FETCH CYCLE 3
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ // FETCH CYCLE 4
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == OK);
+ delete r;
+
+ expected.at(1) = w2;
+ actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ delete d;
+}
+
+TEST_CASE(
+ "Construct singleton dram, store 0, 1th element in three cycles much "
+ "conflict",
+ "[dram]")
+{
+ Dram *d = new Dram(1, 3);
+ 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 w1 = 0x11223344;
+ signed int w2 = 0x55667788;
+
+ // MEMORY CYCLE 1
+ Response *r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+
+ // MEMORY CYCLE 2
+ actual = d->view(0, 1)[0];
+ r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+ // FETCH CYCLE 1
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ r = d->write(MEMORY, w1, 0x00000000);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+ // FETCH CYCLE 1
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ r = d->write(MEMORY, w1, 0x00000000);
+ REQUIRE(r->status == OK);
+ delete r;
+ // NOTE: servicing on the same clock cycle should probably not be allowed
+ // FETCH CYCLE 1
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ expected.at(0) = w1;
+ actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(expected == actual);
+ REQUIRE(r->status == WAIT);
+ delete r;
+
+ r = d->write(FETCH, w2, 0x00000001);
+ actual = d->view(0, 1)[0];
+ REQUIRE(r->status == OK);
+ delete r;
+
+ expected.at(1) = w2;
+ actual = d->view(0, 1)[0];
+ CHECK(expected == actual);
+
delete d;
}