summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/controller.cc2
-rw-r--r--src/sim/dum.cc31
-rw-r--r--src/sim/ex.cc197
-rw-r--r--src/sim/id.cc25
-rw-r--r--src/sim/if.cc4
-rw-r--r--src/sim/instr.cc29
-rw-r--r--src/sim/mm.cc5
-rw-r--r--src/sim/stage.cc35
-rw-r--r--src/sim/wb.cc2
9 files changed, 269 insertions, 61 deletions
diff --git a/src/sim/controller.cc b/src/sim/controller.cc
index 622f1dc..06591af 100644
--- a/src/sim/controller.cc
+++ b/src/sim/controller.cc
@@ -36,3 +36,5 @@ InstrDTO *Controller::advance(Response p)
++this->clock_cycle;
return r;
}
+
+void Controller::advance_helper() {}
diff --git a/src/sim/dum.cc b/src/sim/dum.cc
new file mode 100644
index 0000000..dd16660
--- /dev/null
+++ b/src/sim/dum.cc
@@ -0,0 +1,31 @@
+#include "dum.h"
+#include "accessor.h"
+#include "instrDTO.h"
+#include "response.h"
+#include "stage.h"
+#include "utils.h"
+
+DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; }
+
+InstrDTO *DUM::advance(Response p)
+{
+ InstrDTO *r = curr_instr;
+
+ this->advance_helper();
+ if (this->status == OK && p == OK) {
+ this->curr_instr->set_time_of(this->id, this->clock_cycle);
+ r = new InstrDTO(*this->curr_instr);
+ delete curr_instr;
+ curr_instr = nullptr;
+ }
+
+ return r;
+}
+
+void DUM::advance_helper() {}
+
+void DUM::set_curr_instr(InstrDTO *d)
+{
+ this->curr_instr = d;
+ this->status = OK;
+}
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index 3a1e92c..50882d2 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -1,9 +1,202 @@
#include "ex.h"
#include "accessor.h"
+#include "definitions.h"
#include "instrDTO.h"
#include "response.h"
#include "stage.h"
+#include <unordered_map>
-EX::EX(Stage *stage) : Stage(stage) { this->id = EXEC; }
+// clang-format off
+#define INIT_INSTRUCTION(mnemonic, body) \
+ {mnemonic, [this](signed int &s1, signed int s2) { \
+ body; \
+ }}
+// clang-format on
-InstrDTO *EX::advance(Response p) { return nullptr; }
+EX::EX(Stage *stage) : Stage(stage)
+{
+ this->id = EXEC;
+ instr_map = {
+
+ /* R type instructions */
+ INIT_INSTRUCTION(
+ ADD,
+ {
+ s1 = s1 + s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ SUB,
+ {
+ s1 = s1 - s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ MUL,
+ {
+ s1 = s1 * s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ QUOT,
+ {
+ s1 = s1 / s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ REM,
+ {
+ s1 = s1 % s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ SFTR,
+ {
+ s1 = s1 >> s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ SFTL,
+ {
+ s1 = s1 << s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ AND,
+ {
+ s1 = s1 & s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ OR,
+ {
+ s1 = s1 | s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ NOT,
+ {
+ s1 = ~s1;
+ (void)s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ XOR,
+ {
+ s1 = s1 ^ s2;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ ADDV,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ SUBV,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ MULV,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ DIVV,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
+ INIT_INSTRUCTION(
+ CMP,
+ {
+ (s1 > s2) ? this->set_condition(GT, true)
+ : this->set_condition(GT, false);
+ (s1 == s2) ? this->set_condition(EQ, true)
+ : this->set_condition(EQ, false);
+ }),
+
+ INIT_INSTRUCTION(
+ CEV,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+
+ /* I type instructions */
+ INIT_INSTRUCTION(LOAD, {}),
+
+ INIT_INSTRUCTION(LOADV, {}),
+
+ INIT_INSTRUCTION(ADDI, {}),
+
+ INIT_INSTRUCTION(SUBI, {}),
+
+ INIT_INSTRUCTION(SFTRI, {}),
+
+ INIT_INSTRUCTION(SFTL, {}),
+
+ INIT_INSTRUCTION(ANDI, {}),
+
+ INIT_INSTRUCTION(ORI, {}),
+
+ INIT_INSTRUCTION(XORI, {}),
+
+ INIT_INSTRUCTION(STORE, {}),
+
+ INIT_INSTRUCTION(STOREV, {}),
+
+ /* J type instructions */
+ INIT_INSTRUCTION(JMP, {}),
+
+ INIT_INSTRUCTION(JRL, {}),
+
+ INIT_INSTRUCTION(JAL, {}),
+
+ INIT_INSTRUCTION(BEQ, {}),
+
+ INIT_INSTRUCTION(BGT, {}),
+
+ INIT_INSTRUCTION(BUF, {}),
+
+ INIT_INSTRUCTION(BOF, {}),
+
+ INIT_INSTRUCTION(PUSH, {}),
+
+ INIT_INSTRUCTION(POP, {}),
+
+ /* NOP */
+ INIT_INSTRUCTION(
+ NOP,
+ {
+ (void)s2;
+ (void)s1;
+ (void)this;
+ }),
+ };
+}
+
+void EX::advance_helper() {}
diff --git a/src/sim/id.cc b/src/sim/id.cc
index 969cb9d..36addbb 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -8,26 +8,6 @@
ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; }
-InstrDTO *ID::advance(Response p)
-{
- InstrDTO *r = nullptr;
- Response n;
-
- this->advance_helper();
- if (this->status == OK && p == OK) {
- // mutual consent
- this->curr_instr->set_time_of(this->id, this->clock_cycle);
- r = new InstrDTO(*this->curr_instr);
- delete curr_instr;
- curr_instr = nullptr;
- }
-
- n = (p != OK || this->status != OK) ? BLOCKED : OK;
- // the power of consent
- this->curr_instr = this->next->advance(n);
- return r;
-}
-
void ID::get_instr_fields(
signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
{
@@ -67,7 +47,7 @@ Response ID::read_guard(signed int &v)
{
Response r;
if (this->is_checked_out(v))
- r = BLOCKED;
+ r = STALLED;
else {
r = OK;
v = this->dereference_register(v);
@@ -116,8 +96,9 @@ void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)
r2 = this->read_guard(s2);
this->write_guard(s3);
- this->status = (r1 == BLOCKED || r2 == BLOCKED) ? BLOCKED : OK;
+ this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
}
+
void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3)
{
unsigned int s0b, s1b, s2b;
diff --git a/src/sim/if.cc b/src/sim/if.cc
index 43132ed..77a2704 100644
--- a/src/sim/if.cc
+++ b/src/sim/if.cc
@@ -18,6 +18,7 @@ InstrDTO *IF::advance(Response p)
r = new InstrDTO(*this->curr_instr);
delete curr_instr;
curr_instr = nullptr;
+ this->status = STALLED;
}
return r;
@@ -34,7 +35,6 @@ void IF::advance_helper()
this->status = r;
this->curr_instr = new InstrDTO();
this->curr_instr->set_instr_bits(bits);
- } else
- this->status = STALLED;
+ }
}
}
diff --git a/src/sim/instr.cc b/src/sim/instr.cc
index 08edf5e..e614de5 100644
--- a/src/sim/instr.cc
+++ b/src/sim/instr.cc
@@ -3,36 +3,8 @@
#include <map>
#include <unordered_map>
-// clang-format off
-#define INIT_INSTRUCTION(mnemonic, body) \
- {mnemonic, [](signed int &s1, signed int &s2, signed int &s3) { \
- body; \
- }}
-// clang-format on
-
namespace instr
{
-// clang-format off
-const std::unordered_map<Mnemonic, std::function<void(signed int &s1, signed int &s2, signed int &s3)>>
- // clang-format on
- instr_map = {
-
- /* R type instructions */
- // TODO these need to be WRAPPED with a function that sets overflow.
- // future note to self, if these are more than 2 lines each, you're
- // doing it wrong
- INIT_INSTRUCTION(ADD, s3 = s1 + s2;),
- INIT_INSTRUCTION(SUB, s3 = s1 - s2;),
-
- /* I type instructions */
-
- /* J type instructions */
-
- /* NOP */
- INIT_INSTRUCTION(NOP, (void)s3; (void)s2; (void)s1;),
-
-};
-
const std::unordered_map<unsigned int, Mnemonic> mnemonic_map = {
{0b0000100, ADD}, {0b0001000, SUB}, {0b0001100, MUL},
{0b0010000, QUOT}, {0b0010100, REM}, {0b0011000, SFTR},
@@ -48,6 +20,5 @@ const std::unordered_map<unsigned int, Mnemonic> mnemonic_map = {
{0b0001010, JRL}, {0b0001110, JAL}, {0b0010010, BEQ},
{0b0010110, BGT}, {0b0011010, BUF}, {0b0011110, BOF},
{0b0100010, PUSH}, {0b0100110, POP},
-
};
} // namespace instr
diff --git a/src/sim/mm.cc b/src/sim/mm.cc
index 5bc5836..2b73207 100644
--- a/src/sim/mm.cc
+++ b/src/sim/mm.cc
@@ -6,7 +6,4 @@
MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; }
-InstrDTO *MM::advance(Response p)
-{
- return nullptr;
-}
+void MM::advance_helper() {}
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 62a7fd6..929a4b9 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -7,7 +7,7 @@ Stage::Stage(Stage *next)
{
this->next = next;
this->curr_instr = nullptr;
- this->status = OK;
+ this->status = STALLED;
this->checked_out = {};
}
@@ -21,6 +21,39 @@ Storage *Stage::storage;
bool Stage::is_pipelined;
int Stage::clock_cycle;
+InstrDTO *Stage::advance(Response p)
+{
+ InstrDTO *r = nullptr;
+ Response n;
+
+ this->advance_helper();
+ if (this->status == OK && p == OK) {
+ // mutual consent
+ this->curr_instr->set_time_of(this->id, this->clock_cycle);
+ r = new InstrDTO(*this->curr_instr);
+ delete curr_instr;
+ curr_instr = nullptr;
+ this->status = STALLED;
+ }
+
+ n = (p != OK || this->status != OK) ? STALLED : OK;
+ // the power of consent
+ this->curr_instr = this->next->advance(n);
+ return r;
+}
+
+void Stage::set_condition(CC c, bool v)
+{
+ if (v)
+ 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/src/sim/wb.cc b/src/sim/wb.cc
index 7a8d64c..9337aa0 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -6,4 +6,4 @@
WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; }
-InstrDTO *WB::advance(Response p) { return nullptr; }
+void WB::advance_helper() {}