summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbd <bdunahu@operationnull.com>2025-03-26 12:21:52 -0400
committerbd <bdunahu@operationnull.com>2025-03-26 12:21:52 -0400
commitb81c86b438123457be86af2e7c24375856afa742 (patch)
tree74f271585bce27de2434d8cd826fee09f6a71738
parent9eeea1ab8bf4eb17e5da46d57a6c1d455a0a262e (diff)
Add fetch stage implementation, tests, program loading, DTO object
-rw-r--r--inc/controller.h12
-rw-r--r--inc/dram.h5
-rw-r--r--inc/ex.h3
-rw-r--r--inc/id.h3
-rw-r--r--inc/if.h9
-rw-r--r--inc/instrDTO.h39
-rw-r--r--inc/mm.h3
-rw-r--r--inc/stage.h16
-rw-r--r--inc/wb.h3
-rw-r--r--src/sim/controller.cc27
-rw-r--r--src/sim/ex.cc3
-rw-r--r--src/sim/id.cc3
-rw-r--r--src/sim/if.cc22
-rw-r--r--src/sim/instrDTO.cc15
-rw-r--r--src/sim/mm.cc3
-rw-r--r--src/sim/stage.cc2
-rw-r--r--src/sim/wb.cc3
-rw-r--r--src/storage/dram.cc10
-rw-r--r--tests/controller.cc14
-rw-r--r--tests/if.cc99
20 files changed, 247 insertions, 47 deletions
diff --git a/inc/controller.h b/inc/controller.h
index 56f3836..4b102ce 100644
--- a/inc/controller.h
+++ b/inc/controller.h
@@ -2,6 +2,7 @@
#define CONTROLLER_H
#include "response.h"
#include "stage.h"
+#include "instrDTO.h"
/**
* Houses the clock, and acts as the main API to the GUI.
@@ -11,11 +12,12 @@ class Controller : public Stage
public:
/**
* Constructor.
+ * @param The stage(s) to interface with.
* @param The storage object to use.
* @param Whether or not efficient pipelining will be used.
* @return A newly allocated controller object.
*/
- Controller(Storage *storage, bool is_pipelined);
+ Controller(Stage *stage, Storage *storage, bool is_pipelined);
/**
* Direct the simulator to run for `number` clock cycles.
@@ -34,13 +36,7 @@ class Controller : public Stage
* @return the pc.
*/
int get_pc();
- Response advance();
-
- private:
- /**
- * The current clock cycle.
- */
- int clock_cycle;
+ Response advance(InstrDTO &i) override;
};
#endif /* CONTROLLER_H_INCLUDED */
diff --git a/inc/dram.h b/inc/dram.h
index 0799015..102ec0f 100644
--- a/inc/dram.h
+++ b/inc/dram.h
@@ -29,6 +29,11 @@ class Dram : public Storage
Response
read_word(Accessor accessor, int address, signed int &data) override;
+ /**
+ * TODO This will accept a file at a later date.
+ */
+ void load(std::vector<signed int> program);
+
private:
/**
* Helper for all access methods.
diff --git a/inc/ex.h b/inc/ex.h
index c560eda..f9b2f78 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -1,5 +1,6 @@
#ifndef EX_H
#define EX_H
+#include "instrDTO.h"
#include "response.h"
#include "stage.h"
@@ -8,7 +9,7 @@ class EX : public Stage
public:
using Stage::Stage;
- Response advance();
+ Response advance(InstrDTO &i) override;
};
#endif /* EX_H_INCLUDED */
diff --git a/inc/id.h b/inc/id.h
index dcfda82..de8f677 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -1,5 +1,6 @@
#ifndef ID_H
#define ID_H
+#include "instrDTO.h"
#include "response.h"
#include "stage.h"
@@ -8,7 +9,7 @@ class ID : public Stage
public:
using Stage::Stage;
- Response advance();
+ Response advance(InstrDTO &i) override;
};
#endif /* ID_D_INCLUDED */
diff --git a/inc/if.h b/inc/if.h
index d9599dd..437fa8d 100644
--- a/inc/if.h
+++ b/inc/if.h
@@ -1,5 +1,6 @@
#ifndef IF_H
#define IF_H
+#include "instrDTO.h"
#include "response.h"
#include "stage.h"
@@ -8,7 +9,13 @@ class IF : public Stage
public:
using Stage::Stage;
- Response advance();
+ Response advance(InstrDTO &i) override;
+
+ private:
+ /**
+ * The name this pipeline stages uses to access storage.
+ */
+ const Accessor id = FETCH;
};
#endif /* IF_H_INCLUDED */
diff --git a/inc/instrDTO.h b/inc/instrDTO.h
new file mode 100644
index 0000000..86cec05
--- /dev/null
+++ b/inc/instrDTO.h
@@ -0,0 +1,39 @@
+#ifndef INSTRDTO_H
+#define INSTRDTO_H
+
+class InstrDTO
+{
+ public:
+ /**
+ * Constructor.
+ */
+ InstrDTO();
+ ~InstrDTO() = default;
+
+ /**
+ * @return if_cycle
+ */
+ int get_if_cycle();
+ /**
+ * @return instr_bits
+ */
+ signed int get_instr_bits();
+
+ /**
+ * @param if_cycle
+ */
+ void set_if_cycle(int);
+ /**
+ * @param instr_bits
+ */
+ void set_instr_bits(signed int);
+
+ private:
+ /**
+ * The current clock cycle.
+ */
+ int if_cycle;
+ signed int instr_bits;
+};
+
+#endif /* INSTRDTO_H_INCLUDED */
diff --git a/inc/mm.h b/inc/mm.h
index e9d04d5..5e2b029 100644
--- a/inc/mm.h
+++ b/inc/mm.h
@@ -1,5 +1,6 @@
#ifndef MM_H
#define MM_H
+#include "instrDTO.h"
#include "response.h"
#include "stage.h"
@@ -8,7 +9,7 @@ class MM : public Stage
public:
using Stage::Stage;
- Response advance();
+ Response advance(InstrDTO &i) override;
};
#endif /* MM_H_INCLUDED */
diff --git a/inc/stage.h b/inc/stage.h
index 494f3d3..ac810a9 100644
--- a/inc/stage.h
+++ b/inc/stage.h
@@ -1,6 +1,7 @@
#ifndef STAGE_H
#define STAGE_H
#include "definitions.h"
+#include "instrDTO.h"
#include "response.h"
#include "storage.h"
#include <array>
@@ -8,14 +9,21 @@
class Stage
{
public:
+ /**
+ * Constructor.
+ * @param The next stage in the pipeline.
+ * @return A newly allocated stage object.
+ */
Stage(Stage *next);
virtual ~Stage() = default;
/**
* Advances this stage by a single clock cycle.
+ * @param a DTO object containing various information about an instruction
+ * moving through the pipeline.
* @return a response, indicating whether this pipeline stage is stalled,
* busy, or done.
*/
- virtual Response advance() = 0;
+ virtual Response advance(InstrDTO &i) = 0;
protected:
/**
@@ -37,7 +45,11 @@ class Stage
/**
* A flag indicating whether pipelining should be used.
*/
- bool is_pipelined;
+ static bool is_pipelined;
+ /**
+ * The current clock cycle.
+ */
+ static int clock_cycle;
};
#endif /* STAGE_H_INCLUDED */
diff --git a/inc/wb.h b/inc/wb.h
index 031bf20..b1d65f7 100644
--- a/inc/wb.h
+++ b/inc/wb.h
@@ -2,13 +2,14 @@
#define WB_H
#include "response.h"
#include "stage.h"
+#include "instrDTO.h"
class WB : public Stage
{
public:
using Stage::Stage;
- Response advance();
+ Response advance(InstrDTO &i) override;
};
#endif /* WB_H_INCLUDED */
diff --git a/src/sim/controller.cc b/src/sim/controller.cc
index 93fd0e0..2813905 100644
--- a/src/sim/controller.cc
+++ b/src/sim/controller.cc
@@ -1,34 +1,23 @@
#include "controller.h"
-#include "ex.h"
-#include "id.h"
-#include "if.h"
-#include "mm.h"
#include "response.h"
#include "storage.h"
-#include "wb.h"
-Controller::Controller(Storage *storage, bool is_pipelined)
- : Stage(nullptr)
+Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined)
+ : Stage(stage)
{
this->clock_cycle = 0;
this->storage = storage;
this->is_pipelined = is_pipelined;
this->pc = 0x0;
this->gprs = {0};
-
- IF *f = new IF(nullptr);
- ID *d = new ID(f);
- EX *e = new EX(d);
- MM *m = new MM(e);
- WB *w = new WB(m);
- this->next = w;
}
void Controller::run_for(int number)
{
+ InstrDTO instr;
int i;
for (i = 0; i < number; ++i) {
- this->advance();
+ this->advance(instr);
}
}
@@ -38,9 +27,11 @@ std::array<int, GPR_NUM> Controller::get_gprs() { return this->gprs; }
int Controller::get_pc() { return this->pc; }
-Response Controller::advance()
+Response Controller::advance(InstrDTO &i)
{
- this->next->advance();
+ Response r;
+
+ r = this->next->advance(i);
++this->clock_cycle;
- return OK;
+ return r;
}
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index f286713..1de61d0 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -1,10 +1,11 @@
#include "ex.h"
+#include "instrDTO.h"
#include "logger.h"
#include "response.h"
static Logger *global_log = Logger::getInstance();
-Response EX::advance()
+Response EX::advance(InstrDTO &i)
{
global_log->log(INFO, "hello from execute!");
return OK;
diff --git a/src/sim/id.cc b/src/sim/id.cc
index 56d9549..df55fe2 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -1,10 +1,11 @@
#include "id.h"
+#include "instrDTO.h"
#include "logger.h"
#include "response.h"
static Logger *global_log = Logger::getInstance();
-Response ID::advance()
+Response ID::advance(InstrDTO &i)
{
global_log->log(INFO, "hello from decode!");
return OK;
diff --git a/src/sim/if.cc b/src/sim/if.cc
index 1026072..deed8e1 100644
--- a/src/sim/if.cc
+++ b/src/sim/if.cc
@@ -1,15 +1,19 @@
#include "if.h"
-#include "logger.h"
+#include "accessor.h"
+#include "instrDTO.h"
#include "response.h"
-static Logger *global_log = Logger::getInstance();
-
-Response IF::advance()
+Response IF::advance(InstrDTO &i)
{
- global_log->log(INFO, "hello from fetch!");
- return OK;
-}
-
-
+ Response r;
+ signed int bits;
+ r = this->storage->read_word(this->id, this->pc, bits);
+ if (r == OK) {
+ ++this->pc;
+ i.set_if_cycle(this->clock_cycle);
+ i.set_instr_bits(bits);
+ }
+ return r;
+}
diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc
new file mode 100644
index 0000000..6427b1a
--- /dev/null
+++ b/src/sim/instrDTO.cc
@@ -0,0 +1,15 @@
+#include "instrDTO.h"
+
+InstrDTO::InstrDTO()
+{
+ this->if_cycle = 0;
+ this->instr_bits = 0;
+}
+
+int InstrDTO::get_if_cycle() { return this->if_cycle; }
+
+signed int InstrDTO::get_instr_bits() { return this->instr_bits; }
+
+void InstrDTO::set_if_cycle(int cycle) { this->if_cycle = cycle; }
+
+void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; }
diff --git a/src/sim/mm.cc b/src/sim/mm.cc
index be774ad..28243e7 100644
--- a/src/sim/mm.cc
+++ b/src/sim/mm.cc
@@ -1,10 +1,11 @@
#include "mm.h"
#include "logger.h"
#include "response.h"
+#include "instrDTO.h"
static Logger *global_log = Logger::getInstance();
-Response MM::advance()
+Response MM::advance(InstrDTO &i)
{
global_log->log(INFO, "hello from memory!");
return OK;
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 399743a..0d48774 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -7,3 +7,5 @@ Stage::Stage(Stage *next) {
std::array<int, GPR_NUM> Stage::gprs;
int Stage::pc;
Storage *Stage::storage;
+bool Stage::is_pipelined;
+int Stage::clock_cycle;
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index 83b1c3c..9585fd3 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -1,10 +1,11 @@
#include "wb.h"
+#include "instrDTO.h"
#include "logger.h"
#include "response.h"
static Logger *global_log = Logger::getInstance();
-Response WB::advance()
+Response WB::advance(InstrDTO &i)
{
global_log->log(INFO, "hello from write back!");
return OK;
diff --git a/src/storage/dram.cc b/src/storage/dram.cc
index 371503d..f90f8db 100644
--- a/src/storage/dram.cc
+++ b/src/storage/dram.cc
@@ -56,6 +56,16 @@ Response Dram::read_word(Accessor accessor, int address, signed int &data)
});
}
+// TODO load a file instead and test this method
+void Dram::load(std::vector<signed int> program) {
+ unsigned long i;
+ for (i = 0; i < program.size(); ++i) {
+ int line, word;
+ get_memory_index(i, line, word);
+ this->data->at(line).at(word) = program[i];
+ }
+}
+
Response Dram::process(
Accessor accessor,
int address,
diff --git a/tests/controller.cc b/tests/controller.cc
index a1b8123..a2f8e7d 100644
--- a/tests/controller.cc
+++ b/tests/controller.cc
@@ -1,6 +1,11 @@
#include "controller.h"
#include "cache.h"
#include "dram.h"
+#include "ex.h"
+#include "id.h"
+#include "if.h"
+#include "mm.h"
+#include "wb.h"
#include <algorithm>
#include <catch2/catch_test_macros.hpp>
@@ -10,7 +15,14 @@ class ControllerPipeFixture
ControllerPipeFixture()
{
this->c = new Cache(new Dram(3), 1);
- this->ct = new Controller(this->c, true);
+
+ IF *f = new IF(nullptr);
+ ID *d = new ID(f);
+ EX *e = new EX(d);
+ MM *m = new MM(e);
+ WB *w = new WB(m);
+
+ this->ct = new Controller(w, this->c, true);
}
~ControllerPipeFixture()
{
diff --git a/tests/if.cc b/tests/if.cc
new file mode 100644
index 0000000..6ed6f58
--- /dev/null
+++ b/tests/if.cc
@@ -0,0 +1,99 @@
+#include "if.h"
+#include "cache.h"
+#include "controller.h"
+#include "dram.h"
+#include "instrDTO.h"
+#include <catch2/catch_test_macros.hpp>
+
+class IFPipeFixture
+{
+ public:
+ IFPipeFixture()
+ {
+ Dram *d;
+
+ d = new Dram(3);
+ // 0xC00 is a nop
+ p = {0xC000, 0xC001, 0xC002, 0xC003};
+ d->load(p);
+
+ this->c = new Cache(d, 1);
+ this->f = new IF(nullptr);
+ this->ct = new Controller(this->f, this->c, true);
+ }
+ ~IFPipeFixture()
+ {
+ delete this->ct;
+ delete this->c;
+ };
+
+ /**
+ * Fetch a clean line not in cache.
+ */
+ void fetch_through(InstrDTO &instr)
+ {
+ int i;
+ Response r;
+
+ for (i = 0; i <= MEM_DELAY; ++i) {
+ r = this->ct->advance(instr);
+ // check response
+ CHECK(r == BLOCKED);
+ }
+ this->fetch_cache(instr);
+ }
+
+ /**
+ * Fetch a line in cache.
+ */
+ void fetch_cache(InstrDTO &instr)
+ {
+ int i;
+ Response r;
+
+ for (i = 0; i <= L1_CACHE_DELAY; ++i) {
+ r = this->ct->advance(instr);
+ // check response
+ CHECK(r == WAIT);
+ }
+ r = this->ct->advance(instr);
+ // check response
+ CHECK(r == OK);
+ }
+
+ std::vector<signed int> p;
+ Cache *c;
+ IF *f;
+ Controller *ct;
+};
+
+TEST_CASE_METHOD(IFPipeFixture, "fetch returns single instuction", "[if_pipe]")
+{
+ InstrDTO instr;
+ int expected_cycles;
+
+ expected_cycles = MEM_DELAY + L1_CACHE_DELAY + 2;
+ this->fetch_through(instr);
+
+ CHECK(instr.get_if_cycle() == expected_cycles);
+ REQUIRE(instr.get_instr_bits() == this->p[0]);
+}
+
+TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]")
+{
+ InstrDTO instr;
+ int expected_cycles;
+
+ expected_cycles = MEM_DELAY + L1_CACHE_DELAY + 2;
+ this->fetch_through(instr);
+
+ CHECK(instr.get_if_cycle() == expected_cycles);
+ REQUIRE(instr.get_instr_bits() == this->p[0]);
+
+ // is this right???
+ expected_cycles += L1_CACHE_DELAY + 2;
+ this->fetch_cache(instr);
+
+ CHECK(instr.get_if_cycle() == expected_cycles);
+ REQUIRE(instr.get_instr_bits() == this->p[1]);
+}