diff options
-rw-r--r-- | inc/ex.h | 2 | ||||
-rw-r--r-- | inc/id.h | 32 | ||||
-rw-r--r-- | inc/stage.h | 20 | ||||
-rw-r--r-- | src/sim/ex.cc | 200 | ||||
-rw-r--r-- | src/sim/id.cc | 40 | ||||
-rw-r--r-- | src/sim/stage.cc | 14 | ||||
-rw-r--r-- | tests/ex.cc | 750 | ||||
-rw-r--r-- | tests/id.cc | 64 | ||||
-rw-r--r-- | tests/if.cc | 12 |
9 files changed, 1018 insertions, 116 deletions
@@ -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; }; @@ -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; |