summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-29 17:11:17 -0400
committerbd <bdunahu@operationnull.com>2025-03-29 17:11:17 -0400
commitd21a1a9caa1f1791343a5376121936e552b1124c (patch)
treedf28c01f6d01603e5408bc1b1b111a66adafbff7
parentac0ae7206491a42cdba70560b0db41cfc8c7f642 (diff)
Fetch stage properly holds objects until parent is ready
-rw-r--r--inc/ex.h2
-rw-r--r--inc/id.h2
-rw-r--r--inc/if.h12
-rw-r--r--inc/mm.h2
-rw-r--r--inc/stage.h26
-rw-r--r--inc/wb.h2
-rw-r--r--src/sim/controller.cc4
-rw-r--r--src/sim/ex.cc2
-rw-r--r--src/sim/id.cc11
-rw-r--r--src/sim/if.cc30
-rw-r--r--src/sim/instrDTO.cc1
-rw-r--r--src/sim/mm.cc2
-rw-r--r--src/sim/stage.cc11
-rw-r--r--src/sim/wb.cc2
-rw-r--r--tests/if.cc34
15 files changed, 107 insertions, 36 deletions
diff --git a/inc/ex.h b/inc/ex.h
index c7b7663..e67980d 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -14,7 +14,7 @@ class EX : public Stage
*/
EX(Stage *next);
- Response advance(InstrDTO &i, Response p) override;
+ Response advance(InstrDTO &next_instr, Response p) override;
};
#endif /* EX_H_INCLUDED */
diff --git a/inc/id.h b/inc/id.h
index 95dde37..34e1a47 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -15,7 +15,7 @@ class ID : public Stage
*/
ID(Stage *next);
- Response advance(InstrDTO &i, Response p) override;
+ Response advance(InstrDTO &next_instr, Response p) override;
/**
* Parse an instruction into a type, opcode, and fields. If the type is
diff --git a/inc/if.h b/inc/if.h
index a6869f7..9f84e51 100644
--- a/inc/if.h
+++ b/inc/if.h
@@ -15,7 +15,17 @@ class IF : public Stage
*/
IF(Stage *next);
- Response advance(InstrDTO &i, Response p) override;
+ Response advance(InstrDTO &next_instr, Response p) override;
+
+ private:
+ /**
+ * Performs a fetch only if a current fetch is not pending. Pending means
+ * that a fetch has completed successfully, but the caller stage in the
+ * pipeline is not ready to receive it. In this case, `curr_instr` is not
+ * the nullptr.
+ * @return STALLED if we are waiting on the storage devices, OK otherwise.
+ */
+ void fetch_with_buffer();
};
#endif /* IF_H_INCLUDED */
diff --git a/inc/mm.h b/inc/mm.h
index edee589..0d2ce82 100644
--- a/inc/mm.h
+++ b/inc/mm.h
@@ -14,7 +14,7 @@ class MM : public Stage
*/
MM(Stage *next);
- Response advance(InstrDTO &i, Response p) override;
+ Response advance(InstrDTO &next_instr, Response p) override;
};
#endif /* MM_H_INCLUDED */
diff --git a/inc/stage.h b/inc/stage.h
index 761b9f6..ff4455b 100644
--- a/inc/stage.h
+++ b/inc/stage.h
@@ -7,6 +7,7 @@
#include "storage.h"
#include <array>
#include <set>
+#include <memory>
class Stage
{
@@ -17,17 +18,16 @@ class Stage
* @return A newly allocated stage object.
*/
Stage(Stage *next);
- virtual ~Stage() = default;
+ virtual ~Stage();
/**
* Advances this stage by a single clock cycle.
- * @param a DTO object containing various information about an instruction
- * moving through the pipeline.
+ * @param a DTO object containing the next instruction to be processed.
* @param a response, indicating whether or not the parent pipe stage is
- * busy.
+ * ready to accept a new instruction object next cycle.
* @return a response, indicating whether this pipeline stage is stalling,
* busy, or done.
*/
- virtual Response advance(InstrDTO &i, Response p) = 0;
+ virtual Response advance(InstrDTO &next_instr, Response p) = 0;
protected:
/**
@@ -57,10 +57,6 @@ class Stage
*/
static unsigned int pc;
/**
- * A pointer to the next stage in the pipeline.
- */
- Stage *next;
- /**
* A pointer to the top-level storage device.
*/
static Storage *storage;
@@ -72,6 +68,18 @@ class Stage
* The current clock cycle.
*/
static int clock_cycle;
+ /**
+ * A pointer to the next stage in the pipeline.
+ */
+ Stage *next;
+ /**
+ * A pointer to the current instruction this stage is processing.
+ */
+ std::unique_ptr<InstrDTO> curr_instr;
+ /**
+ * The current status of this stage.
+ */
+ Response status;
private:
/**
diff --git a/inc/wb.h b/inc/wb.h
index c1a6a32..9a708a6 100644
--- a/inc/wb.h
+++ b/inc/wb.h
@@ -14,7 +14,7 @@ class WB : public Stage
*/
WB(Stage *next);
- Response advance(InstrDTO &i, Response p) override;
+ Response advance(InstrDTO &next_instr, Response p) override;
};
#endif /* WB_H_INCLUDED */
diff --git a/src/sim/controller.cc b/src/sim/controller.cc
index 833d900..17937eb 100644
--- a/src/sim/controller.cc
+++ b/src/sim/controller.cc
@@ -29,11 +29,11 @@ std::array<int, GPR_NUM> Controller::get_gprs() { return this->gprs; }
int Controller::get_pc() { return this->pc; }
-Response Controller::advance(InstrDTO &i, Response p)
+Response Controller::advance(InstrDTO &next_instr, Response p)
{
Response r;
- r = this->next->advance(i, p);
+ r = this->next->advance(next_instr, p);
++this->clock_cycle;
return r;
}
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index c9c2116..5b561f8 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -6,4 +6,4 @@
EX::EX(Stage *stage) : Stage(stage) { this->id = EXEC; }
-Response EX::advance(InstrDTO &i, Response p) { return OK; }
+Response EX::advance(InstrDTO &next_instr, Response p) { return OK; }
diff --git a/src/sim/id.cc b/src/sim/id.cc
index 70fab9a..83a8751 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -8,15 +8,16 @@
ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; }
-Response ID::advance(InstrDTO &i, Response p)
+Response ID::advance(InstrDTO &next_instr, Response p)
{
Response r;
- signed int s1, s2, s3;
- Mnemonic m;
+ r = OK;
+ // signed int s1, s2, s3;
+ // Mnemonic m;
- s1 = i.get_instr_bits();
+ // s1 = next_instr.get_instr_bits();
- get_instr_fields(s1, s2, s3, m);
+ // get_instr_fields(s1, s2, s3, m);
return r;
}
diff --git a/src/sim/if.cc b/src/sim/if.cc
index 099ff1c..de044f8 100644
--- a/src/sim/if.cc
+++ b/src/sim/if.cc
@@ -6,17 +6,31 @@
IF::IF(Stage *stage) : Stage(stage) { this->id = FETCH; }
-Response IF::advance(InstrDTO &i, Response p)
+Response IF::advance(InstrDTO &next_instr, Response p)
+{
+ this->fetch_with_buffer();
+ if (this->status == OK && p == OK) {
+ // mutual consent
+ ++this->pc;
+ this->curr_instr->set_time_of(this->id, this->clock_cycle);
+ next_instr = *this->curr_instr;
+ curr_instr = nullptr;
+ }
+ return this->status;
+}
+
+void IF::fetch_with_buffer()
{
Response r;
signed int bits;
- r = this->storage->read_word(this->id, this->pc, bits);
- if (r == OK) {
- ++this->pc;
- i.set_time_of(this->id, this->clock_cycle);
- i.set_instr_bits(bits);
+ if (this->curr_instr == nullptr) {
+ r = this->storage->read_word(this->id, this->pc, bits);
+ if (r == OK) {
+ this->status = r;
+ this->curr_instr = std::make_unique<InstrDTO>();
+ this->curr_instr->set_instr_bits(bits);
+ } else
+ this->status = STALLED;
}
-
- return r;
}
diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc
index 7418033..5a7fe3b 100644
--- a/src/sim/instrDTO.cc
+++ b/src/sim/instrDTO.cc
@@ -7,6 +7,7 @@ InstrDTO::InstrDTO()
this->s1 = 0;
this->s2 = 0;
this->s3 = 0;
+ this->mnemonic = NOP;
}
int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; }
diff --git a/src/sim/mm.cc b/src/sim/mm.cc
index 93c5b87..f394420 100644
--- a/src/sim/mm.cc
+++ b/src/sim/mm.cc
@@ -6,7 +6,7 @@
MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; }
-Response MM::advance(InstrDTO &i, Response p)
+Response MM::advance(InstrDTO &next_instr, Response p)
{
return OK;
}
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 8d9dfc0..48ee494 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -5,7 +5,14 @@
static Logger *global_log = Logger::getInstance();
-Stage::Stage(Stage *next) { this->next = next; }
+Stage::Stage(Stage *next)
+{
+ this->next = next;
+ this->curr_instr = nullptr;
+ this->status = OK;
+}
+
+Stage::~Stage() { delete this->next; };
std::array<int, GPR_NUM> Stage::gprs;
std::array<int, V_NUM> Stage::vrs;
@@ -19,7 +26,7 @@ Response Stage::check_out(unsigned int &v)
{
Response r;
if (this->is_checked_out(v))
- r = STALLED;
+ r = BLOCKED;
else {
r = OK;
v = this->check_out_register(v);
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index 13ab66a..bdea65a 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -6,4 +6,4 @@
WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; }
-Response WB::advance(InstrDTO &i, Response p) { return OK; }
+Response WB::advance(InstrDTO &next_instr, Response p) { return OK; }
diff --git a/tests/if.cc b/tests/if.cc
index 3be3305..bb25afa 100644
--- a/tests/if.cc
+++ b/tests/if.cc
@@ -38,7 +38,7 @@ class IFPipeFixture
for (i = 0; i < this->m_delay + 1; ++i) {
r = this->ct->advance(instr, OK);
// check response
- CHECK(r == BLOCKED);
+ CHECK(r == STALLED);
}
this->fetch_cache(instr);
}
@@ -54,7 +54,7 @@ class IFPipeFixture
for (i = 0; i < this->c_delay; ++i) {
r = this->ct->advance(instr, OK);
// check response
- CHECK(r == WAIT);
+ CHECK(r == STALLED);
}
r = this->ct->advance(instr, OK);
// check response
@@ -98,3 +98,33 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]")
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]);
+}