summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/ex.h2
-rw-r--r--inc/id.h32
-rw-r--r--inc/stage.h20
-rw-r--r--src/sim/ex.cc200
-rw-r--r--src/sim/id.cc40
-rw-r--r--src/sim/stage.cc14
-rw-r--r--tests/ex.cc750
-rw-r--r--tests/id.cc64
-rw-r--r--tests/if.cc12
9 files changed, 1018 insertions, 116 deletions
diff --git a/inc/ex.h b/inc/ex.h
index cc8062b..6d4254e 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -25,7 +25,7 @@ class EX : public Stage
*/
std::unordered_map<
Mnemonic,
- std::function<void(signed int &s1, signed int s2)>>
+ std::function<void(signed int &s1, signed int s2, signed int s3)>>
instr_map;
};
diff --git a/inc/id.h b/inc/id.h
index 9911440..3ff5063 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -21,22 +21,6 @@ class ID : public Stage
*/
/**
- * Parse an instruction into a type, opcode, and fields. If the type is
- * invalid, only the type field will be set.
- *
- * This method is marked public so it may be tested, and is not used outside
- * of this class during normal execution.
- *
- * @param the resulting first field, which varies per type. To call this
- * function properly, this field must contain the full instruction bytes on
- * function entry.
- * @param the resulting second field, which varies per type.
- * @param the resulting third field, which varies per type.
- * @param the resulting mnemonic.
- */
- void get_instr_fields(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
- /**
* Facilitates register checkout and data hazard management.
* It does this by checking that the register passed in is not currently
* checked out. If true, then replaces r with the value of the register and
@@ -66,6 +50,22 @@ class ID : public Stage
* @param the resulting second field.
* @param the resulting third field.
*/
+ /**
+ * Parse an instruction into a type, opcode, and fields. If the type is
+ * invalid, only the type field will be set.
+ *
+ * This method is marked public so it may be tested, and is not used outside
+ * of this class during normal execution.
+ *
+ * @param the resulting first field, which varies per type. To call this
+ * function properly, this field must contain the full instruction bytes on
+ * function entry.
+ * @param the resulting second field, which varies per type.
+ * @param the resulting third field, which varies per type.
+ * @param the resulting mnemonic.
+ */
+ void get_instr_fields(
+ signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
void decode_R_type(signed int &s1, signed int &s2, signed int &s3);
void decode_I_type(signed int &s1, signed int &s2, signed int &s3);
void decode_J_type(signed int &s1, signed int &s2);
diff --git a/inc/stage.h b/inc/stage.h
index 56a3589..84d2a7b 100644
--- a/inc/stage.h
+++ b/inc/stage.h
@@ -40,6 +40,21 @@ class Stage
*/
virtual InstrDTO *advance(Response p);
+ /* The following methods are made public so that they may be tested, and are
+ * not to be called from outside classes during standard execution.
+ */
+
+ /**
+ * Gets the bit in the condition code register correspondng to `c`.
+ * @param the condition code to retrieve,
+ */
+ bool get_condition(CC c);
+
+ /**
+ * Sets the value of the PC register.
+ */
+ void set_pc(unsigned int pc);
+
protected:
/**
* The function expected to do the majority of the work.
@@ -54,11 +69,6 @@ class Stage
*/
void set_condition(CC c, bool v);
/**
- * Gets the bit in the condition code register correspondng to `c`.
- * @param the condition code to retrieve,
- */
- bool get_condition(CC c);
- /**
* Helper for `check_out`.
* Returns true if r are not checked out, false otherwise.
* @param a list of register numbers.
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index 50882d2..95cce8d 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -8,7 +8,7 @@
// clang-format off
#define INIT_INSTRUCTION(mnemonic, body) \
- {mnemonic, [this](signed int &s1, signed int s2) { \
+ {mnemonic, [this](signed int &s1, signed int s2, signed int s3) { \
body; \
}}
// clang-format on
@@ -23,6 +23,7 @@ EX::EX(Stage *stage) : Stage(stage)
ADD,
{
s1 = s1 + s2;
+ (void)s3;
(void)this;
}),
@@ -30,6 +31,7 @@ EX::EX(Stage *stage) : Stage(stage)
SUB,
{
s1 = s1 - s2;
+ (void)s3;
(void)this;
}),
@@ -37,6 +39,7 @@ EX::EX(Stage *stage) : Stage(stage)
MUL,
{
s1 = s1 * s2;
+ (void)s3;
(void)this;
}),
@@ -44,6 +47,7 @@ EX::EX(Stage *stage) : Stage(stage)
QUOT,
{
s1 = s1 / s2;
+ (void)s3;
(void)this;
}),
@@ -51,6 +55,7 @@ EX::EX(Stage *stage) : Stage(stage)
REM,
{
s1 = s1 % s2;
+ (void)s3;
(void)this;
}),
@@ -58,6 +63,7 @@ EX::EX(Stage *stage) : Stage(stage)
SFTR,
{
s1 = s1 >> s2;
+ (void)s3;
(void)this;
}),
@@ -65,6 +71,7 @@ EX::EX(Stage *stage) : Stage(stage)
SFTL,
{
s1 = s1 << s2;
+ (void)s3;
(void)this;
}),
@@ -72,6 +79,7 @@ EX::EX(Stage *stage) : Stage(stage)
AND,
{
s1 = s1 & s2;
+ (void)s3;
(void)this;
}),
@@ -79,6 +87,7 @@ EX::EX(Stage *stage) : Stage(stage)
OR,
{
s1 = s1 | s2;
+ (void)s3;
(void)this;
}),
@@ -86,6 +95,7 @@ EX::EX(Stage *stage) : Stage(stage)
NOT,
{
s1 = ~s1;
+ (void)s3;
(void)s2;
(void)this;
}),
@@ -94,12 +104,14 @@ EX::EX(Stage *stage) : Stage(stage)
XOR,
{
s1 = s1 ^ s2;
+ (void)s3;
(void)this;
}),
INIT_INSTRUCTION(
ADDV,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
@@ -108,6 +120,7 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
SUBV,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
@@ -116,6 +129,7 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
MULV,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
@@ -124,6 +138,7 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
DIVV,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
@@ -136,62 +151,185 @@ EX::EX(Stage *stage) : Stage(stage)
: this->set_condition(GT, false);
(s1 == s2) ? this->set_condition(EQ, true)
: this->set_condition(EQ, false);
+ (void)s3;
}),
INIT_INSTRUCTION(
CEV,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
}),
/* I type instructions */
- INIT_INSTRUCTION(LOAD, {}),
+ INIT_INSTRUCTION(
+ LOAD,
+ {
+ s1 = s1 + s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(LOADV, {}),
+ INIT_INSTRUCTION(
+ LOADV,
+ {
+ (void)s3;
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
- INIT_INSTRUCTION(ADDI, {}),
+ INIT_INSTRUCTION(
+ ADDI,
+ {
+ s1 = s1 + s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(SUBI, {}),
+ INIT_INSTRUCTION(
+ SUBI,
+ {
+ s1 = s1 - s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(SFTRI, {}),
+ INIT_INSTRUCTION(
+ SFTRI,
+ {
+ s1 = s1 >> s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(SFTL, {}),
+ INIT_INSTRUCTION(
+ SFTLI,
+ {
+ s1 = s1 << s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(ANDI, {}),
+ INIT_INSTRUCTION(
+ ANDI,
+ {
+ s1 = s1 & s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(ORI, {}),
+ INIT_INSTRUCTION(
+ ORI,
+ {
+ s1 = s1 | s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(XORI, {}),
+ INIT_INSTRUCTION(
+ XORI,
+ {
+ s1 = s1 ^ s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(STORE, {}),
+ INIT_INSTRUCTION(
+ STORE,
+ {
+ s1 = s1 + s3;
+ (void)s2;
+ (void)this;
+ }),
- INIT_INSTRUCTION(STOREV, {}),
+ INIT_INSTRUCTION(
+ STOREV,
+ {
+ (void)s3;
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
/* J type instructions */
- INIT_INSTRUCTION(JMP, {}),
+ INIT_INSTRUCTION(
+ JMP,
+ {
+ s1 = s1 + s2;
+ (void)s3;
+ (void)this;
+ }),
- INIT_INSTRUCTION(JRL, {}),
+ INIT_INSTRUCTION(
+ JRL,
+ {
+ s1 = this->pc + s2;
+ (void)s3;
+ (void)this;
+ }),
- INIT_INSTRUCTION(JAL, {}),
+ INIT_INSTRUCTION(
+ JAL,
+ {
+ s1 = s1 + s2;
+ (void)s3;
+ (void)this;
+ }),
- INIT_INSTRUCTION(BEQ, {}),
+ INIT_INSTRUCTION(
+ BEQ,
+ {
+ s1 = this->pc + s2;
+ (void)s3;
+ }),
- INIT_INSTRUCTION(BGT, {}),
+ INIT_INSTRUCTION(
+ BGT,
+ {
+ s1 = this->pc + s2;
+ (void)s3;
+ }),
- INIT_INSTRUCTION(BUF, {}),
+ INIT_INSTRUCTION(
+ BUF,
+ {
+ s1 = this->pc + s2;
+ (void)s3;
+ }),
- INIT_INSTRUCTION(BOF, {}),
+ INIT_INSTRUCTION(
+ BOF,
+ {
+ s1 = this->pc + s2;
+ (void)s3;
+ }),
- INIT_INSTRUCTION(PUSH, {}),
+ INIT_INSTRUCTION(
+ PUSH,
+ {
+ (void)s3;
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
- INIT_INSTRUCTION(POP, {}),
+ INIT_INSTRUCTION(
+ POP,
+ {
+ (void)s3;
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
/* NOP */
INIT_INSTRUCTION(
NOP,
{
+ (void)s3;
(void)s2;
(void)s1;
(void)this;
@@ -199,4 +337,22 @@ EX::EX(Stage *stage) : Stage(stage)
};
}
-void EX::advance_helper() {}
+void EX::advance_helper()
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+
+ // it may be good to ensure we are not doing
+ // work that has already been done
+ if (this->curr_instr) {
+ m = this->curr_instr->get_mnemonic();
+ s1 = this->curr_instr->get_s1();
+ s2 = this->curr_instr->get_s2();
+ s3 = this->curr_instr->get_s3();
+
+ this->instr_map[m](s1, s2, s3);
+
+ this->curr_instr->set_s1(s1);
+ this->status = OK;
+ }
+}
diff --git a/src/sim/id.cc b/src/sim/id.cc
index 36addbb..edf74e2 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -8,25 +8,6 @@
ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; }
-void ID::get_instr_fields(
- signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
-{
- unsigned int type;
- this->split_instr(s1, type, m);
-
- switch (type) {
- case 0b00:
- this->decode_R_type(s1, s2, s3);
- break;
- case 0b01:
- this->decode_I_type(s1, s2, s3);
- break;
- case 0b10:
- this->decode_J_type(s1, s2);
- break;
- }
-}
-
void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m)
{
unsigned int opcode, opcode_size;
@@ -80,6 +61,27 @@ void ID::advance_helper()
}
}
+void ID::get_instr_fields(
+ signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
+{
+ unsigned int type;
+ this->split_instr(s1, type, m);
+
+ switch (type) {
+ case 0b00:
+ this->decode_R_type(s1, s2, s3);
+ break;
+ case 0b01:
+ this->decode_I_type(s1, s2, s3);
+ break;
+ case 0b10:
+ this->decode_J_type(s1, s2);
+ break;
+ case 0b11:
+ this->status = OK;
+ }
+}
+
void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)
{
unsigned int s0b, s1b, s2b;
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 929a4b9..2c03741 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -21,6 +21,14 @@ Storage *Stage::storage;
bool Stage::is_pipelined;
int Stage::clock_cycle;
+bool Stage::get_condition(CC c) {
+ return (this->gprs[3] >> c) & 1;
+}
+
+void Stage::set_pc(unsigned int pc) {
+ this->pc = pc;
+}
+
InstrDTO *Stage::advance(Response p)
{
InstrDTO *r = nullptr;
@@ -45,15 +53,11 @@ InstrDTO *Stage::advance(Response p)
void Stage::set_condition(CC c, bool v)
{
if (v)
- this->gprs[3] = this->gprs[3] & 1 << c;
+ this->gprs[3] = this->gprs[3] | 1 << c;
else
this->gprs[3] = this->gprs[3] & ~(1 << c);
}
-bool Stage::get_condition(CC c) {
- return (this->gprs[3] >> c) & 1;
-}
-
signed int Stage::dereference_register(signed int v)
{
signed int r;
diff --git a/tests/ex.cc b/tests/ex.cc
new file mode 100644
index 0000000..9def9fe
--- /dev/null
+++ b/tests/ex.cc
@@ -0,0 +1,750 @@
+#include "ex.h"
+#include "cache.h"
+#include "controller.h"
+#include "dram.h"
+#include "dum.h"
+#include "instr.h"
+#include "instrDTO.h"
+#include <catch2/catch_test_macros.hpp>
+
+class EXFixture
+{
+ public:
+ EXFixture()
+ {
+ this->dr = new Dram(3);
+ this->c = new Cache(this->dr, 1);
+ this->dum = new DUM(nullptr);
+ this->e = new EX(dum);
+ this->ct = new Controller(this->e, this->c, true);
+ };
+ ~EXFixture()
+ {
+ delete this->ct;
+ delete this->c;
+ };
+ InstrDTO *
+ execute_instr(signed int s1, signed int s2, signed int s3, Mnemonic m)
+ {
+ InstrDTO *i = new InstrDTO();
+ i->set_s1(s1);
+ i->set_s2(s2);
+ i->set_s3(s3);
+ i->set_mnemonic(m);
+ this->dum->set_curr_instr(i);
+
+ i = this->ct->advance(OK);
+ REQUIRE(i == nullptr);
+ i = this->ct->advance(OK);
+ REQUIRE(i != nullptr);
+
+ return i;
+ }
+ Dram *dr;
+ Cache *c;
+ EX *e;
+ DUM *dum;
+ Controller *ct;
+};
+
+TEST_CASE_METHOD(EXFixture, "ADD within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = ADD;
+ s1 = 42000, s2 = -41958, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "ADD overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "ADD underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SUB within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SUB;
+ s1 = 200, s2 = 131, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SUB overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SUB underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "MUL within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = MUL;
+ s1 = 200, s2 = 200, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 40000);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "MUL overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "MUL underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "QUOT within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = QUOT;
+ s1 = 2043, s2 = 40, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 51);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "QUOT overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "QUOT underflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "QUOT halt", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "REM within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = REM;
+ s1 = 2043, s2 = 40, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 3);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "REM overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "REM underflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "REM halt", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SFTR within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SFTR;
+ s1 = 1300, s2 = 6, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 20);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SFTR overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SFTR underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SFTL within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SFTL;
+ s1 = 13, s2 = 6, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 832);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SFTL overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SFTL underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "AND", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = AND;
+ s1 = 1234, s2 = 5678, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 1026);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "OR", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = OR;
+ s1 = 1234, s2 = 5678, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 5886);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "NOT", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = NOT;
+ s1 = 1234, s2 = -1, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == -1235);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "XOR", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = XOR;
+ s1 = 1234, s2 = 5678, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 4860);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "ADDV within bounds", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "ADDV overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "ADDV underflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SUBV within bounds", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SUBV overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SUBV underflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "MULV within bounds", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "MULV overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "MULV underflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "DIVV within bounds", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "DIVV overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "DIVV underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "CMP less", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = CMP;
+ s1 = -1, s2 = 0, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ // should not be changed
+ CHECK(i->get_s1() == -1);
+
+ CHECK(!ct->get_condition(EQ));
+ CHECK(!ct->get_condition(GT));
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "CMP equal", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = CMP;
+ s1 = 20, s2 = 20, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ // should not be changed
+ CHECK(i->get_s1() == 20);
+
+ CHECK(ct->get_condition(EQ));
+ CHECK(!ct->get_condition(GT));
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "CMP greater", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = CMP;
+ s1 = 21, s2 = 20, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ // should not be changed
+ CHECK(i->get_s1() == 21);
+
+ CHECK(!ct->get_condition(EQ));
+ CHECK(ct->get_condition(GT));
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "CEQ less", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "CEQ equal", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "CEQ greater", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "LOAD", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = LOAD;
+ s1 = 42000, s2 = 0;
+ s3 = -41958;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "LOADV", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "ADDI within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = ADDI;
+ s1 = 42000, s2 = 0;
+ s3 = -41958;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "ADDI overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "ADDI underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SUBI within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SUBI;
+ s1 = 200, s2 = 0;
+ s3 = 131;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SUBI overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SUBI underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SFTRI within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SFTRI;
+ s1 = 1300, s2 = 0, s3 = 6;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 20);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SFTRI overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SFTRI underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "SFTLI within bounds", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = SFTLI;
+ s1 = 13, s2 = 0, s3 = 6;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 832);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "SFTLI overflow", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "SFTLI underflow", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "ANDI", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = ANDI;
+ s1 = 1234, s2 = 0, s3 = 5678;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 1026);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "ORI", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = ORI;
+ s1 = 1234, s2 = 0, s3 = 5678;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 5886);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "XORI", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = XORI;
+ s1 = 1234, s2 = 0, s3 = 5678;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 4860);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "STORE", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = LOAD;
+ s1 = 42000, s2 = 0, s3 = -41958;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "STOREV", "[ex]")
+// {
+// }
+
+TEST_CASE_METHOD(EXFixture, "JMP", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = JMP;
+ s1 = 42000, s2 = -41958, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "JRL", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = JRL;
+ s1 = 100, s2 = -42027, s3;
+ this->ct->set_pc(42096);
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "JAL", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = JAL;
+ s1 = 42000, s2 = -41958, s3 = 0;
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 42);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = BEQ;
+ s1 = 100, s2 = -42027, s3 = 0;
+ this->ct->set_pc(42096);
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "BGT", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = BGT;
+ s1 = 100, s2 = -42027, s3 = 0;
+ this->ct->set_pc(42096);
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "BUF", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = BUF;
+ s1 = 100, s2 = -42027, s3 = 0;
+ this->ct->set_pc(42096);
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+TEST_CASE_METHOD(EXFixture, "BOF", "[ex]")
+{
+ signed int s1, s2, s3;
+ Mnemonic m;
+ InstrDTO *i;
+
+ m = BOF;
+ s1 = 100, s2 = -42027, s3 = 0;
+ this->ct->set_pc(42096);
+ i = execute_instr(s1, s2, s3, m);
+
+ CHECK(i->get_s1() == 69);
+ CHECK(!ct->get_condition(OF));
+ CHECK(!ct->get_condition(UF));
+
+ delete i;
+}
+
+// TEST_CASE_METHOD(EXFixture, "PUSH", "[ex]")
+// {
+// }
+
+// TEST_CASE_METHOD(EXFixture, "POP", "[ex]")
+// {
+// }
diff --git a/tests/id.cc b/tests/id.cc
index be50ed5..5270972 100644
--- a/tests/id.cc
+++ b/tests/id.cc
@@ -23,11 +23,18 @@ class IDFixture
delete this->ct;
delete this->c;
};
- void prime_bits(signed int raw)
+ InstrDTO *decode_bits(signed int raw)
{
InstrDTO *i = new InstrDTO();
i->set_instr_bits(raw);
this->dum->set_curr_instr(i);
+
+ i = this->ct->advance(OK);
+ REQUIRE(i == nullptr);
+ i = this->ct->advance(OK);
+ REQUIRE(i != nullptr);
+
+ return i;
}
signed int encode_R_type(
signed int s3,
@@ -79,12 +86,15 @@ class IDFixture
TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]")
{
- signed int s1 = 0, s2 = 0, s3 = 0;
- Mnemonic m;
+ signed int t;
+ InstrDTO *i;
- s1 = 0xFFFFFFFF;
- this->d->get_instr_fields(s1, s2, s3, m);
- CHECK(m == NOP);
+ t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b11);
+ i = this->decode_bits(t);
+
+ CHECK(i->get_mnemonic() == NOP);
+
+ delete i;
}
TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]")
@@ -93,12 +103,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]")
InstrDTO *i;
t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b0);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0x00000000);
@@ -114,12 +119,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]")
InstrDTO *i;
t = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0x00000000);
@@ -135,12 +135,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]")
InstrDTO *i;
t = this->encode_I_type(0xF, 0b1, 0b10, 0b0111, 0b1);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0x00000000);
@@ -156,12 +151,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]")
InstrDTO *i;
t = this->encode_I_type(0xCC, 0b010, 0b101, 0b1011, 0b1);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0x00000000);
@@ -177,12 +167,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]")
InstrDTO *i;
t = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0x3456);
@@ -197,12 +182,7 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]")
InstrDTO *i;
t = this->encode_J_type(0xBBCCF, 0b10101, 0b0011, 0b10);
- this->prime_bits(t);
-
- i = this->ct->advance(OK);
- REQUIRE(i == nullptr);
- i = this->ct->advance(OK);
- REQUIRE(i != nullptr);
+ i = this->decode_bits(t);
CHECK(i->get_s1() == 0x00000000); // registers are empty
CHECK(i->get_s2() == 0xBBCCF);
diff --git a/tests/if.cc b/tests/if.cc
index 1f02cb0..4ebc47d 100644
--- a/tests/if.cc
+++ b/tests/if.cc
@@ -5,10 +5,10 @@
#include "instrDTO.h"
#include <catch2/catch_test_macros.hpp>
-class IFPipeFixture
+class IFFixture
{
public:
- IFPipeFixture()
+ IFFixture()
{
Dram *d;
@@ -21,7 +21,7 @@ class IFPipeFixture
this->f = new IF(nullptr);
this->ct = new Controller(this->f, this->c, true);
}
- ~IFPipeFixture()
+ ~IFFixture()
{
delete this->ct;
delete this->c;
@@ -70,7 +70,7 @@ class IFPipeFixture
Controller *ct;
};
-TEST_CASE_METHOD(IFPipeFixture, "fetch returns single instuction", "[if_pipe]")
+TEST_CASE_METHOD(IFFixture, "fetch returns single instuction", "[if_pipe]")
{
InstrDTO *i;
int expected_cycles;
@@ -83,7 +83,7 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns single instuction", "[if_pipe]")
delete i;
}
-TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]")
+TEST_CASE_METHOD(IFFixture, "fetch returns two instuctions", "[if_pipe]")
{
InstrDTO *i;
int expected_cycles;
@@ -103,7 +103,7 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]")
delete i;
}
-TEST_CASE_METHOD(IFPipeFixture, "fetch waits with old instruction",
+TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction",
"[if_pipe]")
{
InstrDTO *i;