summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/c11.h54
-rw-r--r--tests/cache.cc167
-rw-r--r--tests/cache_1_1.cc111
-rw-r--r--tests/cache_2_1.cc87
-rw-r--r--tests/dram.cc38
-rw-r--r--tests/utils.cc65
6 files changed, 272 insertions, 250 deletions
diff --git a/tests/c11.h b/tests/c11.h
new file mode 100644
index 0000000..e5599db
--- /dev/null
+++ b/tests/c11.h
@@ -0,0 +1,54 @@
+#include "cache.h"
+#include "dram.h"
+#include "storage.h"
+#include <algorithm>
+#include <array>
+#include <catch2/catch_test_macros.hpp>
+#include <functional>
+
+/**
+ * one way associative, single level
+ */
+class C11
+{
+ public:
+ C11()
+ {
+ this->m_delay = 4;
+ this->c_delay = 2;
+ this->mem = new int();
+ this->fetch = new int();
+ this->c = new Cache(new Dram(this->m_delay), 5, 0, this->c_delay);
+ this->expected = {0, 0, 0, 0};
+ this->actual = this->c->view(0, 1)[0];
+ }
+
+ ~C11()
+ {
+ delete this->c;
+ delete this->mem;
+ delete this->fetch;
+ }
+
+ void
+ wait_then_do(int delay, std::function<int()> f)
+ {
+ for (int i = 0; i < delay; ++i) {
+ int r = f();
+
+ // check response
+ CHECK(!r);
+ // check for early modifications
+ actual = c->view(0, 1)[0];
+ REQUIRE(this->expected == this->actual);
+ }
+ }
+
+ int m_delay;
+ int c_delay;
+ Cache *c;
+ int *mem;
+ int *fetch;
+ std::array<signed int, LINE_SIZE> expected;
+ std::array<signed int, LINE_SIZE> actual;
+};
diff --git a/tests/cache.cc b/tests/cache.cc
deleted file mode 100644
index 313f93f..0000000
--- a/tests/cache.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-#include "cache.h"
-#include "dram.h"
-#include <catch2/catch_test_macros.hpp>
-
-class CacheFixture
-{
- public:
- CacheFixture()
- {
- this->m_delay = 4;
- this->c_delay = 2;
- this->d = new Dram(this->m_delay);
- this->c = new Cache(this->d, this->c_delay);
- this->mem = new int;
- this->fetch = new int;
- this->expected = {0, 0, 0, 0};
- this->actual = this->c->view(0, 1)[0];
- }
-
- ~CacheFixture()
- {
- delete this->c;
- delete this->mem;
- delete this->fetch;
- }
-
- /**
- * An operation that is done a lot.
- */
- void
- wait_for_storage(int delay, int expected, std::function<int()> f)
- {
- for (int i = 0; i < delay; ++i) {
- int r = f();
-
- // check response
- CHECK(r == expected);
- // check for early modifications
- actual = c->view(0, 1)[0];
- REQUIRE(this->expected == this->actual);
- }
- }
-
- int m_delay;
- int c_delay;
- Cache *c;
- Dram *d;
- int *mem;
- int *fetch;
- std::array<signed int, LINE_SIZE> expected;
- std::array<signed int, LINE_SIZE> actual;
-};
-
-TEST_CASE_METHOD(CacheFixture, "store 0th element in DELAY cycles", "[dram]")
-{
- int r;
- signed int w;
- CHECK(expected == actual);
-
- w = 0x11223344;
- // delay + 1 due to internal logic, when mem
- // finishes handle_miss still returns 'blocked'
- this->wait_for_storage(this->m_delay + this->c_delay + 1, 0, [this, w]() {
- return this->c->write_word(this->mem, w, 0b0);
- });
-
- r = c->write_word(this->mem, w, 0b0);
- CHECK(r);
-
- actual = this->d->view(0, 1)[0];
- // we do NOT write back now!
- REQUIRE(expected == actual);
-
- expected.at(0) = w;
- actual = c->view(0, 1)[0];
- REQUIRE(expected == actual);
-}
-
-TEST_CASE_METHOD(CacheFixture, "store 0th, 1st element in DELAY cycles, with conflict", "[cache]")
-{
- signed int w;
- int r, i;
- CHECK(expected == actual);
-
- w = 0x11223344;
- // delay + 1 due to internal logic, when mem
- // finishes handle_miss still returns 'blocked'
- for (i = 0; i < this->m_delay + this->c_delay + 1; ++i) {
- r = c->write_word(this->mem, w, 0b0);
- CHECK(!r);
- r = c->write_word(this->fetch, w, 0b1);
- CHECK(!r);
-
- // check for early modifications
- actual = c->view(0, 1)[0];
- REQUIRE(this->expected == this->actual);
- }
-
- r = c->write_word(this->mem, w, 0b0);
- CHECK(r);
-
- actual = d->view(0, 1)[0];
- // we do NOT write back now!
- REQUIRE(expected == actual);
-
- expected.at(0) = w;
- actual = c->view(0, 1)[0];
- REQUIRE(expected == actual);
-
- // this should have been loaded already!
- this->wait_for_storage(
- this->c_delay, 0, [this, w]() { return this->c->write_word(this->fetch, w, 0b1); });
-
- r = c->write_word(this->fetch, w, 0b1);
- CHECK(r);
-
- expected.at(1) = w;
- actual = c->view(0, 1)[0];
- REQUIRE(expected == actual);
-}
-
-TEST_CASE_METHOD(
- CacheFixture, "store 0th, 1st element different tags, in DELAY cycles, no conflict", "[cache]")
-{
- int r;
- signed int w;
- CHECK(expected == actual);
-
- w = 0x11223344;
- // delay + 1 due to internal logic, when mem
- // finishes handle_miss still returns 'blocked'
- this->wait_for_storage(this->m_delay + this->c_delay + 1, 0, [this, w]() {
- return this->c->write_word(this->mem, w, 0b0);
- });
-
- r = c->write_word(this->mem, w, 0b0);
- CHECK(r);
-
- expected.at(0) = w;
- actual = c->view(0, 1)[0];
- REQUIRE(expected == actual);
-
- // write back to memory
- // fetch new address (don't run the completion cycle yet)
- this->wait_for_storage(this->m_delay + this->m_delay + 1, 0, [this, w]() {
- return this->c->write_word(this->fetch, w, 0b10000001);
- });
-
- // after the fetch, this cache line should be empty
- this->c->write_word(this->fetch, w, 0b10000001);
- CHECK(r);
-
- expected.at(0) = 0;
- actual = c->view(0, 1)[0];
- CHECK(expected == actual);
-
- this->wait_for_storage(
- this->c_delay, 0, [this, w]() { return this->c->write_word(this->fetch, w, 0b10000001); });
-
- r = c->write_word(this->fetch, w, 0b10000001);
- CHECK(r);
-
- expected.at(0) = 0;
- expected.at(1) = w;
- actual = c->view(0, 1)[0];
- REQUIRE(expected == actual);
-}
diff --git a/tests/cache_1_1.cc b/tests/cache_1_1.cc
new file mode 100644
index 0000000..7d16f76
--- /dev/null
+++ b/tests/cache_1_1.cc
@@ -0,0 +1,111 @@
+#include "c11.h"
+#include "cache.h"
+#include "dram.h"
+#include <catch2/catch_test_macros.hpp>
+
+TEST_CASE_METHOD(C11, "store 0th element in DELAY cycles", "[dram]")
+{
+ int r;
+ signed int w;
+ CHECK(expected == actual);
+
+ w = 0x11223344;
+ // delay + 1 due to internal logic, when mem
+ // finishes is_address_missing still returns '1'
+ this->wait_then_do(this->m_delay + this->c_delay + 1, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b0);
+ });
+
+ r = c->write_word(this->mem, w, 0b0);
+ CHECK(r);
+
+ expected.at(0) = w;
+ actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+}
+
+TEST_CASE_METHOD(C11, "store 0th, 1st element in DELAY cycles, with conflict", "[cache]")
+{
+ signed int w;
+ int r, i;
+ CHECK(expected == actual);
+
+ w = 0x11223344;
+ // delay + 1 due to internal logic, when mem
+ // finishes is_address_missing still returns '1'
+ for (i = 0; i < this->m_delay + this->c_delay + 1; ++i) {
+ r = c->write_word(this->mem, w, 0b0);
+ CHECK(!r);
+ r = c->write_word(this->fetch, w, 0b1);
+ CHECK(!r);
+
+ // check for early modifications
+ actual = c->view(0, 1)[0];
+ REQUIRE(this->expected == this->actual);
+ }
+
+ r = c->write_word(this->mem, w, 0b0);
+ CHECK(r);
+
+ expected.at(0) = w;
+ actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ // this should have been loaded already!
+ this->wait_then_do(
+ this->c_delay, [this, w]() { return this->c->write_word(this->fetch, w, 0b1); });
+
+ r = c->write_word(this->fetch, w, 0b1);
+ CHECK(r);
+
+ expected.at(1) = w;
+ actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+}
+
+TEST_CASE_METHOD(
+ C11, "store 0th, 1st element different tags, in DELAY cycles, no conflict", "[cache]")
+{
+ int r;
+ signed int w;
+ CHECK(expected == actual);
+
+ w = 0x11223344;
+ // delay + 1 due to internal logic, when mem
+ // finishes is_address_missing still returns '1'
+ this->wait_then_do(this->m_delay + this->c_delay + 1, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b0);
+ });
+
+ r = c->write_word(this->mem, w, 0b0);
+ CHECK(r);
+
+ expected.at(0) = w;
+ actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ // write back to memory
+ // fetch new address (don't run the completion cycle yet)
+ this->wait_then_do(this->m_delay + this->m_delay + 1, [this, w]() {
+ return this->c->write_word(this->fetch, w, 0b10000001);
+ });
+
+ // after the fetch, this cache line should be empty
+ this->c->write_word(this->fetch, w, 0b10000001);
+ CHECK(r);
+
+ expected.at(0) = 0;
+ actual = c->view(0, 1)[0];
+ CHECK(expected == actual);
+
+ this->wait_then_do(
+ this->c_delay, [this, w]() { return this->c->write_word(this->fetch, w, 0b10000001); });
+
+ r = c->write_word(this->fetch, w, 0b10000001);
+ CHECK(r);
+
+ expected.at(0) = 0;
+ expected.at(1) = w;
+ actual = c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+}
diff --git a/tests/cache_2_1.cc b/tests/cache_2_1.cc
new file mode 100644
index 0000000..cb48d2a
--- /dev/null
+++ b/tests/cache_2_1.cc
@@ -0,0 +1,87 @@
+#include "c11.h"
+#include "cache.h"
+#include "dram.h"
+#include "storage.h"
+#include <catch2/catch_test_macros.hpp>
+#include <iostream>
+
+/**
+ * One way associative, two level
+ * Assuming that each address is 14 bits (16384 word address space):
+ * LEVEL1: OFFSET=2, INDEX=5(32), TAG=7
+ * LEVEL2: OFFSET=2, INDEX=7(128), TAG=5
+ */
+class C21 : public C11
+{
+ public:
+ C21() : C11()
+ {
+ this->c2 = new Cache(new Dram(this->m_delay), 7, 0, this->c_delay);
+ this->c = new Cache(this->c2, 5, 0, this->c_delay);
+ }
+
+ Cache *c2;
+};
+
+// TEST_CASE_METHOD(C21, "store 32th, 33rd element in DELAY cycles",
+
+TEST_CASE_METHOD(C21, "store 32th, 96th element in DELAY cycles, evict to level 2", "[2level_cache]")
+{
+ int r;
+ signed int w;
+ CHECK(expected == actual);
+
+ w = 0x11223344;
+ // delay + 1 due to internal logic, when mem
+ // finishes handle_miss still returns 'blocked'
+ this->wait_then_do(this->m_delay + (this->c_delay * 2) + 2, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b10000000);
+ });
+
+ r = this->c->write_word(this->mem, w, 0b10000000);
+ CHECK(r);
+
+ // check level 2
+ // note this is write-back == no write
+ actual = this->c2->view(32, 1)[0];
+ REQUIRE(expected == actual);
+
+ // check level 1
+ expected.at(0) = w;
+ actual = this->c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+
+ // wait = evict
+ this->wait_then_do(this->c_delay + 1, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b110000000);
+ });
+
+ // check level 2
+ actual = this->c2->view(32, 1)[0];
+ REQUIRE(expected == actual);
+
+ // read in line
+ this->wait_then_do(this->m_delay + this->c_delay + 1, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b110000000);
+ });
+
+ expected.at(0) = 0;
+ // perform write
+ this->wait_then_do(this->c_delay + 1, [this, w]() {
+ return this->c->write_word(this->mem, w, 0b110000000);
+ });
+
+ r = this->c->write_word(this->mem, w, 0b110000000);
+ CHECK(r);
+
+ // check level 2
+ actual = this->c2->view(96, 1)[0];
+ REQUIRE(expected == actual);
+ expected.at(0) = w;
+ actual = this->c2->view(32, 1)[0];
+ REQUIRE(expected == actual);
+
+ // check level 1
+ actual = this->c->view(0, 1)[0];
+ REQUIRE(expected == actual);
+}
diff --git a/tests/dram.cc b/tests/dram.cc
index 086ca4a..06a7720 100644
--- a/tests/dram.cc
+++ b/tests/dram.cc
@@ -2,10 +2,10 @@
#include <array>
#include <catch2/catch_test_macros.hpp>
-class DramFixture
+class D
{
public:
- DramFixture()
+ D()
{
this->delay = 3;
this->d = new Dram(this->delay);
@@ -15,7 +15,7 @@ class DramFixture
this->actual = this->d->view(0, 1)[0];
}
- ~DramFixture()
+ ~D()
{
delete this->d;
delete this->mem;
@@ -44,14 +44,15 @@ class DramFixture
std::array<signed int, LINE_SIZE> actual;
};
-TEST_CASE_METHOD(DramFixture, "store 0th element in DELAY cycles", "[dram]")
+TEST_CASE_METHOD(D, "store 0th element in DELAY cycles", "[dram]")
{
int r;
signed int w;
CHECK(expected == actual);
w = 0x11223344;
- this->wait_for_storage(this->delay, [this, w]() { return this->d->write_word(this->mem, w, 0x0); });
+ this->wait_for_storage(
+ this->delay, [this, w]() { return this->d->write_word(this->mem, w, 0x0); });
r = this->d->write_word(this->mem, w, 0x0);
@@ -61,14 +62,15 @@ TEST_CASE_METHOD(DramFixture, "store 0th element in DELAY cycles", "[dram]")
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(DramFixture, "store 0th, 1st element in DELAY cycles, no conflict", "[dram]")
+TEST_CASE_METHOD(D, "store 0th, 1st element in DELAY cycles, no conflict", "[dram]")
{
int r;
signed int w;
CHECK(expected == actual);
w = 0x11223344;
- this->wait_for_storage(this->delay, [this, w]() { return this->d->write_word(this->mem, w, 0x0); });
+ this->wait_for_storage(
+ this->delay, [this, w]() { return this->d->write_word(this->mem, w, 0x0); });
r = d->write_word(this->mem, w, 0x0);
REQUIRE(r);
@@ -77,7 +79,8 @@ TEST_CASE_METHOD(DramFixture, "store 0th, 1st element in DELAY cycles, no confli
actual = d->view(0, 1)[0];
REQUIRE(expected == actual);
- this->wait_for_storage(this->delay, [this, w]() { return this->d->write_word(this->fetch, w, 0x1); });
+ this->wait_for_storage(
+ this->delay, [this, w]() { return this->d->write_word(this->fetch, w, 0x1); });
r = d->write_word(this->fetch, w, 0x1);
CHECK(r);
@@ -87,7 +90,7 @@ TEST_CASE_METHOD(DramFixture, "store 0th, 1st element in DELAY cycles, no confli
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(DramFixture, "store 0th element in DELAY cycles with conflict", "[dram]")
+TEST_CASE_METHOD(D, "store 0th element in DELAY cycles with conflict", "[dram]")
{
int r, i;
signed int w;
@@ -112,7 +115,8 @@ TEST_CASE_METHOD(DramFixture, "store 0th element in DELAY cycles with conflict",
actual = d->view(0, 1)[0];
REQUIRE(expected == actual);
- this->wait_for_storage(this->delay, [this, w]() { return this->d->write_word(this->fetch, w, 0x1); });
+ this->wait_for_storage(
+ this->delay, [this, w]() { return this->d->write_word(this->fetch, w, 0x1); });
r = d->write_word(this->fetch, w, 0x1);
CHECK(r);
@@ -122,7 +126,7 @@ TEST_CASE_METHOD(DramFixture, "store 0th element in DELAY cycles with conflict",
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles", "[dram]")
+TEST_CASE_METHOD(D, "store line in DELAY cycles", "[dram]")
{
int r;
signed int w;
@@ -142,7 +146,7 @@ TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles", "[dram]")
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles no conflict", "[dram]")
+TEST_CASE_METHOD(D, "store line in DELAY cycles no conflict", "[dram]")
{
int r;
signed int w;
@@ -173,7 +177,7 @@ TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles no conflict", "[dram]"
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles with conflict", "[dram]")
+TEST_CASE_METHOD(D, "store line in DELAY cycles with conflict", "[dram]")
{
int r, i;
signed int w;
@@ -212,8 +216,7 @@ TEST_CASE_METHOD(DramFixture, "store line in DELAY cycles with conflict", "[dram
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(
- DramFixture, "store line in DELAY cycles, read in DELAY cycles, no conflict", "[dram]")
+TEST_CASE_METHOD(D, "store line in DELAY cycles, read in DELAY cycles, no conflict", "[dram]")
{
int r, i, addr;
signed int w;
@@ -242,8 +245,7 @@ TEST_CASE_METHOD(
REQUIRE(expected == actual);
}
-TEST_CASE_METHOD(
- DramFixture, "store line in DELAY cycles, read in DELAY cycles with conflict", "[dram]")
+TEST_CASE_METHOD(D, "store line in DELAY cycles, read in DELAY cycles with conflict", "[dram]")
{
int r, i, addr;
signed int w;
@@ -276,7 +278,7 @@ TEST_CASE_METHOD(
}
TEST_CASE_METHOD(
- DramFixture,
+ D,
"store line in DELAY cycles, read one element at a time in DELAY cycles "
"with conflict",
"[dram]")
diff --git a/tests/utils.cc b/tests/utils.cc
deleted file mode 100644
index 2e0e934..0000000
--- a/tests/utils.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "utils.h"
-#include "definitions.h"
-#include <catch2/catch_test_macros.hpp>
-
-TEST_CASE("Parse arbitrary fields # one", "[utils]")
-{
- int tag, index, offset;
- int address = 0b0001010101;
- get_cache_fields(address, &tag, &index, &offset);
- CHECK(tag == 0b000);
- CHECK(index == 0b10101);
- CHECK(offset == 0b01);
-}
-
-TEST_CASE("Parse arbitrary fields # two", "[utils]")
-{
- int tag, index, offset;
- int address = 0b0100111011;
- get_cache_fields(address, &tag, &index, &offset);
- CHECK(tag == 0b010);
- CHECK(index == 0b01110);
- CHECK(offset == 0b11);
-}
-
-TEST_CASE("wrap address outside upper bound", "[utils]")
-{
- int address = MEM_WORDS + 25;
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == 25);
-}
-
-TEST_CASE("wrap address inside upper bound", "[utils]")
-{
- int address = MEM_WORDS - 25;
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == MEM_WORDS - 25);
-}
-
-TEST_CASE("wrap address at upper bound", "[utils]")
-{
- int address = MEM_WORDS;
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == 0);
-}
-
-TEST_CASE("wrap address lower than 0 with magnitude lesser than mem size", "[utils]")
-{
- int address = -10;
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == MEM_WORDS - 10);
-}
-
-TEST_CASE("wrap address lower than 0 but with magnitude greater than mem size", "[utils]")
-{
- int address = -(MEM_WORDS + 10);
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == MEM_WORDS - 10);
-}
-
-TEST_CASE("wrap address at 0", "[utils]")
-{
- int address = 0;
- int wrapped = wrap_address(address);
- REQUIRE(wrapped == 0);
-}