summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/id.h21
-rw-r--r--inc/if.h2
-rw-r--r--src/sim/id.cc130
-rw-r--r--src/sim/if.cc4
4 files changed, 91 insertions, 66 deletions
diff --git a/inc/id.h b/inc/id.h
index f8c167d..49637ce 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -17,6 +17,10 @@ class ID : public Stage
Response advance(InstrDTO &next_instr, Response p) override;
+ /* The following methods are made public so that they may be tested, and are
+ * not to be called from outside classes during standard execution.
+ */
+
/**
* Parse an instruction into a type, opcode, and fields. If the type is
* invalid, only the type field will be set.
@@ -33,11 +37,6 @@ class ID : public Stage
*/
void get_instr_fields(
signed int &s1, signed int &s2, signed int &s3, Mnemonic &m);
-
- /* The following methods are made public so that they may be tested, and are
- * not to be called from outside classes during standard execution.
- */
-
/**
* Facilitates register checkout and data hazard management.
* It does this by checking that the register passed in is not currently
@@ -57,11 +56,15 @@ class ID : public Stage
void write_guard(signed int &r);
private:
- // TODO write me
/**
- * Helper for ``
- * Attempts to parse and dereference instruction arguments. If a desc
-
+ * Decodes `curr_instr` and sets status to BLOCKED if a data hazard occurs.
+ */
+ void advance_helper();
+ /**
+ * Helper for `get_instr_fields`
+ * Attempts to parse and dereference instruction arguments. Uses read and
+ * write guards to prevent RAW conflicts.
+ *
* @param the resulting first field. To call this function properly, this
* field must contain the section of the instruction to be parsed.
* @param the resulting second field.
diff --git a/inc/if.h b/inc/if.h
index 9f84e51..3fafe53 100644
--- a/inc/if.h
+++ b/inc/if.h
@@ -25,7 +25,7 @@ class IF : public Stage
* the nullptr.
* @return STALLED if we are waiting on the storage devices, OK otherwise.
*/
- void fetch_with_buffer();
+ void advance_helper();
};
#endif /* IF_H_INCLUDED */
diff --git a/src/sim/id.cc b/src/sim/id.cc
index c04b31f..68ac555 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -5,68 +5,26 @@
#include "logger.h"
#include "response.h"
#include "stage.h"
-#include <algorithm>
ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; }
Response ID::advance(InstrDTO &next_instr, Response p)
{
- Response r;
- signed int s1, s2, s3;
- Mnemonic m;
-
- s1 = next_instr.get_instr_bits();
-
- get_instr_fields(s1, s2, s3, m);
- return r;
-}
-
-void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)
-{
- unsigned int s0b, s1b, s2b;
- Response r1, r2;
-
- s0b = REG_SIZE;
- s1b = s0b + REG_SIZE;
- s2b = s1b + REG_SIZE;
- s3 = GET_MID_BITS(s1, s1b, s2b);
- s2 = GET_MID_BITS(s1, s0b, s1b);
- s1 = GET_LS_BITS(s1, s0b);
-
- r1 = this->read_guard(s1);
- r2 = this->read_guard(s2);
- this->write_guard(s3);
-
- this->status = std::max(r1, r2);
-}
-void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3)
-{
- unsigned int s0b, s1b, s2b;
-
- s0b = REG_SIZE;
- s1b = s0b + REG_SIZE;
- s2b = WORD_SPEC;
- s3 = GET_MID_BITS(s1, s1b, s2b);
- s2 = GET_MID_BITS(s1, s0b, s1b);
- s1 = GET_LS_BITS(s1, s0b);
-
- this->status = this->read_guard(s1);
- this->write_guard(s2);
-}
-
-void ID::decode_J_type(signed int &s1, signed int &s2)
-{
- unsigned int s0b, s1b;
-
- s0b = REG_SIZE;
- s1b = WORD_SPEC;
- s2 = GET_MID_BITS(s1, s0b, s1b);
- s1 = GET_LS_BITS(s1, s0b);
+ Response n;
+
+ this->advance_helper();
+ if (this->status == OK && p == OK) {
+ // mutual consent
+ this->curr_instr->set_time_of(this->id, this->clock_cycle);
+ next_instr = *this->curr_instr;
+ curr_instr = nullptr;
+ }
- this->status = this->read_guard(*&s1);
+ n = (p != OK || this->status != OK) ? BLOCKED : OK;
+ // the power of consent
+ n = this->next->advance(next_instr, n);
}
-// TODO this function is ugly
void ID::get_instr_fields(
signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
{
@@ -119,3 +77,67 @@ void ID::write_guard(signed int &v)
this->checked_out.push_back(v);
v = this->dereference_register(v);
}
+
+void ID::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) {
+ s1 = curr_instr->get_instr_bits();
+ get_instr_fields(s1, s2, s3, m);
+ if (this->status == OK) {
+ curr_instr->set_s1(s1);
+ curr_instr->set_s2(s2);
+ curr_instr->set_s3(s3);
+ curr_instr->set_mnemonic(m);
+ }
+ }
+}
+
+void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)
+{
+ unsigned int s0b, s1b, s2b;
+ Response r1, r2;
+
+ s0b = REG_SIZE;
+ s1b = s0b + REG_SIZE;
+ s2b = s1b + REG_SIZE;
+ s3 = GET_MID_BITS(s1, s1b, s2b);
+ s2 = GET_MID_BITS(s1, s0b, s1b);
+ s1 = GET_LS_BITS(s1, s0b);
+
+ r1 = this->read_guard(s1);
+ r2 = this->read_guard(s2);
+ this->write_guard(s3);
+
+ this->status = (r1 == BLOCKED || r2 == BLOCKED) ? BLOCKED : OK;
+}
+void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3)
+{
+ unsigned int s0b, s1b, s2b;
+
+ s0b = REG_SIZE;
+ s1b = s0b + REG_SIZE;
+ s2b = WORD_SPEC;
+ s3 = GET_MID_BITS(s1, s1b, s2b);
+ s2 = GET_MID_BITS(s1, s0b, s1b);
+ s1 = GET_LS_BITS(s1, s0b);
+
+ this->status = this->read_guard(s1);
+ this->write_guard(s2);
+}
+
+void ID::decode_J_type(signed int &s1, signed int &s2)
+{
+ unsigned int s0b, s1b;
+
+ s0b = REG_SIZE;
+ s1b = WORD_SPEC;
+ s2 = GET_MID_BITS(s1, s0b, s1b);
+ s1 = GET_LS_BITS(s1, s0b);
+
+ this->status = this->read_guard(*&s1);
+}
diff --git a/src/sim/if.cc b/src/sim/if.cc
index de044f8..7d3291b 100644
--- a/src/sim/if.cc
+++ b/src/sim/if.cc
@@ -8,7 +8,7 @@ IF::IF(Stage *stage) : Stage(stage) { this->id = FETCH; }
Response IF::advance(InstrDTO &next_instr, Response p)
{
- this->fetch_with_buffer();
+ this->advance_helper();
if (this->status == OK && p == OK) {
// mutual consent
++this->pc;
@@ -19,7 +19,7 @@ Response IF::advance(InstrDTO &next_instr, Response p)
return this->status;
}
-void IF::fetch_with_buffer()
+void IF::advance_helper()
{
Response r;
signed int bits;