summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/id.cc251
-rw-r--r--tests/if.cc46
-rw-r--r--tests/utils.cc8
3 files changed, 293 insertions, 12 deletions
diff --git a/tests/id.cc b/tests/id.cc
new file mode 100644
index 0000000..d9c1701
--- /dev/null
+++ b/tests/id.cc
@@ -0,0 +1,251 @@
+#include "id.h"
+#include "cache.h"
+#include "controller.h"
+#include "dram.h"
+#include "if.h"
+#include "instr.h"
+#include "instrDTO.h"
+#include <catch2/catch_test_macros.hpp>
+
+class IDFixture
+{
+ public:
+ IDFixture()
+ {
+ Dram *dr;
+
+ dr = new Dram(3);
+ this->c = new Cache(dr, 1);
+ IF *f = new IF(nullptr);
+ this->d = new ID(f);
+ this->ct = new Controller(this->d, this->c, true);
+ };
+ ~IDFixture()
+ {
+ delete this->ct;
+ delete this->c;
+ };
+ signed int encode_R_type(
+ signed int s3,
+ signed int s2,
+ signed int s1,
+ signed int opcode,
+ signed int type)
+ {
+ signed int t;
+ t = s3;
+ t = (t << REG_SIZE) + s2;
+ t = (t << REG_SIZE) + s1;
+ t = (t << R_OPCODE_SIZE) + opcode;
+ t = (t << TYPE_SIZE) + type;
+ return t;
+ }
+ signed int encode_I_type(
+ signed int s3,
+ signed int s2,
+ signed int s1,
+ signed int opcode,
+ signed int type)
+ {
+ signed int t;
+ t = s3;
+ t = (t << REG_SIZE) + s2;
+ t = (t << REG_SIZE) + s1;
+ t = (t << OPCODE_SIZE) + opcode;
+ t = (t << TYPE_SIZE) + type;
+ return t;
+ }
+ signed int encode_J_type(
+ signed int s2, signed int s1, signed int opcode, signed int type)
+ {
+ signed int t;
+ t = s2;
+ t = (t << REG_SIZE) + s1;
+ t = (t << OPCODE_SIZE) + opcode;
+ t = (t << TYPE_SIZE) + type;
+ return t;
+ }
+ Cache *c;
+ ID *d;
+ Controller *ct;
+};
+
+TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]")
+{
+ signed int s1 = 0, s2 = 0, s3 = 0;
+ Mnemonic m;
+
+ s1 = 0xFFFFFFFF;
+ this->d->get_instr_fields(s1, s2, s3, m);
+ CHECK(m == NOP);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b0);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0x00000000);
+ CHECK(s3 == 0x00000000);
+ CHECK(m == MUL);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0b00000000);
+ CHECK(s3 == 0b00000000);
+ CHECK(m == SUB);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_I_type(0xF, 0b1, 0b10, 0b0111, 0b1);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0x00000000);
+ CHECK(s3 == 0xF);
+ CHECK(m == SFTLI);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_I_type(0xCC, 0b010, 0b101, 0b1011, 0b1);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0x00000000);
+ CHECK(s3 == 0xCC);
+ CHECK(m == STORE);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0x3456);
+ CHECK(m == BOF);
+ // behavior does nothing
+ CHECK(s3 == -1);
+}
+
+TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]")
+{
+ signed int s1 = -1, s2 = -1, s3 = -1;
+ Mnemonic m;
+
+ s1 = this->encode_J_type(0xBBCCF, 0b10101, 0b0011, 0b10);
+ this->d->get_instr_fields(s1, s2, s3, m);
+
+ CHECK(s1 == 0x00000000); // registers are empty
+ CHECK(s2 == 0xBBCCF);
+ CHECK(m == JAL);
+ // behavior does nothing
+ CHECK(s3 == -1);
+}
+
+TEST_CASE_METHOD(IDFixture, "read does not conflict with read", "[id]")
+{
+ signed int v;
+ Response r;
+
+ v = 0b1;
+ r = this->d->read_guard(v);
+ CHECK(v == 0b0);
+ REQUIRE(r == OK);
+
+ v = 0b1;
+ this->d->read_guard(v);
+ REQUIRE(v == 0b0);
+}
+
+TEST_CASE_METHOD(IDFixture, "write does not conflict with write", "[id]")
+{
+ signed int v;
+
+ v = 0b1;
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+
+ v = 0b1;
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+}
+
+TEST_CASE_METHOD(IDFixture, "write does not conflict with read", "[id]")
+{
+ signed int v;
+ Response r;
+
+ v = 0b1;
+ r = this->d->read_guard(v);
+ CHECK(v == 0b0);
+ REQUIRE(r == OK);
+
+ v = 0b1;
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+}
+
+TEST_CASE_METHOD(IDFixture, "read does conflict with write", "[id]")
+{
+ signed int v;
+ Response r;
+
+ v = 0b1;
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+
+ v = 0b1;
+ r = this->d->read_guard(v);
+ CHECK(v == 0b01);
+ REQUIRE(r == BLOCKED);
+}
+
+TEST_CASE_METHOD(IDFixture, "stores indefinite conflicts", "[id]")
+{
+ signed int v, ov;
+ Response r;
+
+ v = 0b0;
+ ov = v;
+ while (v < 0b110) {
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+ v = ++ov;
+ }
+ this->d->write_guard(v);
+ REQUIRE(v == 0b0);
+
+ v = 0b110;
+ r = this->d->read_guard(v);
+ CHECK(v == 0b110);
+ REQUIRE(r == BLOCKED);
+
+ v = 0b0;
+ r = this->d->read_guard(v);
+ CHECK(v == 0b0);
+ REQUIRE(r == BLOCKED);
+}
diff --git a/tests/if.cc b/tests/if.cc
index 5c1b645..bb25afa 100644
--- a/tests/if.cc
+++ b/tests/if.cc
@@ -36,9 +36,9 @@ class IFPipeFixture
Response r;
for (i = 0; i < this->m_delay + 1; ++i) {
- r = this->ct->advance(instr);
+ r = this->ct->advance(instr, OK);
// check response
- CHECK(r == BLOCKED);
+ CHECK(r == STALLED);
}
this->fetch_cache(instr);
}
@@ -52,11 +52,11 @@ class IFPipeFixture
Response r;
for (i = 0; i < this->c_delay; ++i) {
- r = this->ct->advance(instr);
+ r = this->ct->advance(instr, OK);
// check response
- CHECK(r == WAIT);
+ CHECK(r == STALLED);
}
- r = this->ct->advance(instr);
+ r = this->ct->advance(instr, OK);
// check response
CHECK(r == OK);
}
@@ -77,7 +77,7 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns single instuction", "[if_pipe]")
expected_cycles = this->m_delay + this->c_delay + 2;
this->fetch_through(instr);
- CHECK(instr.get_if_cycle() == expected_cycles);
+ CHECK(instr.get_time_of(FETCH) == expected_cycles);
REQUIRE(instr.get_instr_bits() == this->p[0]);
}
@@ -89,12 +89,42 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]")
expected_cycles = this->m_delay + this->c_delay + 2;
this->fetch_through(instr);
- CHECK(instr.get_if_cycle() == expected_cycles);
+ CHECK(instr.get_time_of(FETCH) == expected_cycles);
REQUIRE(instr.get_instr_bits() == this->p[0]);
expected_cycles += this->c_delay + 1;
this->fetch_cache(instr);
- CHECK(instr.get_if_cycle() == expected_cycles);
+ CHECK(instr.get_time_of(FETCH) == expected_cycles);
REQUIRE(instr.get_instr_bits() == this->p[1]);
}
+
+TEST_CASE_METHOD(IFPipeFixture, "fetch waits with old instruction", "[if_pipe]")
+{
+ Response r;
+ InstrDTO instr;
+ int i, expected_cycles, fetch_cycles;
+
+ fetch_cycles = this->m_delay + this->c_delay + 2;
+ expected_cycles = this->m_delay + (this->c_delay * 2) + 1;
+
+ for (i = 0; i < this->m_delay + 1; ++i) {
+ r = this->ct->advance(instr, BLOCKED);
+ // check response
+ CHECK(r == STALLED);
+ }
+ for (i = 0; i < this->c_delay; ++i) {
+ r = this->ct->advance(instr, BLOCKED);
+ // check response
+ CHECK(r == STALLED);
+ }
+ for (i = 0; i < expected_cycles - fetch_cycles; ++i) {
+ r = this->ct->advance(instr, BLOCKED);
+ // check response
+ CHECK(r == OK);
+ }
+
+ r = this->ct->advance(instr, OK);
+ CHECK(instr.get_time_of(FETCH) == expected_cycles);
+ REQUIRE(instr.get_instr_bits() == this->p[0]);
+}
diff --git a/tests/utils.cc b/tests/utils.cc
index ea1a1ed..2e0e934 100644
--- a/tests/utils.cc
+++ b/tests/utils.cc
@@ -2,21 +2,21 @@
#include "definitions.h"
#include <catch2/catch_test_macros.hpp>
-TEST_CASE("Parse arbitrary fields # one", "[cache]")
+TEST_CASE("Parse arbitrary fields # one", "[utils]")
{
int tag, index, offset;
int address = 0b0001010101;
- get_bit_fields(address, &tag, &index, &offset);
+ get_cache_fields(address, &tag, &index, &offset);
CHECK(tag == 0b000);
CHECK(index == 0b10101);
CHECK(offset == 0b01);
}
-TEST_CASE("Parse arbitrary fields # two", "[cache]")
+TEST_CASE("Parse arbitrary fields # two", "[utils]")
{
int tag, index, offset;
int address = 0b0100111011;
- get_bit_fields(address, &tag, &index, &offset);
+ get_cache_fields(address, &tag, &index, &offset);
CHECK(tag == 0b010);
CHECK(index == 0b01110);
CHECK(offset == 0b11);