summaryrefslogtreecommitdiff
path: root/src/sim
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim')
-rw-r--r--src/sim/controller.cc16
-rw-r--r--src/sim/ex.cc22
-rw-r--r--src/sim/id.cc34
-rw-r--r--src/sim/if.cc3
-rw-r--r--src/sim/mm.cc11
-rw-r--r--src/sim/stage.cc1
-rw-r--r--src/sim/wb.cc8
7 files changed, 79 insertions, 16 deletions
diff --git a/src/sim/controller.cc b/src/sim/controller.cc
index 65e5676..db6106c 100644
--- a/src/sim/controller.cc
+++ b/src/sim/controller.cc
@@ -1,4 +1,5 @@
#include "controller.h"
+#include "ex.h"
#include "response.h"
#include "storage.h"
@@ -8,9 +9,11 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined)
this->clock_cycle = 1;
this->storage = storage;
this->is_pipelined = is_pipelined;
+ this->is_empty = true;
this->pc = 0x0;
this->checked_out = {};
this->gprs = {0};
+ this->gprs.at(2) = MEM_WORDS; // set the stack pointer
// grant side-door access
this->id = SIDE;
}
@@ -19,7 +22,11 @@ void Controller::run_for(int number)
{
int i;
for (i = 0; i < number; ++i) {
- this->advance(WAIT);
+ try {
+ this->advance(WAIT);
+ } catch (HaltException &e) {
+ break;
+ }
}
}
@@ -27,10 +34,6 @@ int Controller::get_clock_cycle() { return this->clock_cycle; }
std::array<int, GPR_NUM> Controller::get_gprs() { return this->gprs; }
-void Controller::set_gprs(int index, int value) { this->gprs[index] = value; }
-
-void Controller::set_pipelined(bool value) { this->is_pipelined = value; }
-
int Controller::get_pc() { return this->pc; }
InstrDTO *Controller::advance(Response p)
@@ -39,6 +42,9 @@ InstrDTO *Controller::advance(Response p)
r = this->next->advance(p);
++this->clock_cycle;
+ if (r)
+ this->is_empty = true;
+
return r;
}
diff --git a/src/sim/ex.cc b/src/sim/ex.cc
index d20d15f..62e39c1 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -49,15 +49,15 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
QUOT,
{
- s1 = s1 / s2;
+ this->handle_divide(s1, s2, false);
(void)pc;
(void)s3;
- (void)this;
}),
INIT_INSTRUCTION(
REM,
{
+ this->handle_divide(s1, s2, true);
s1 = s1 % s2;
(void)pc;
(void)s3;
@@ -340,20 +340,18 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
PUSH,
{
+ s1 = s1 + s3;
(void)pc;
- (void)s3;
(void)s2;
- (void)s1;
(void)this;
}),
INIT_INSTRUCTION(
POP,
{
+ s1 = s1 + s3;
(void)pc;
- (void)s3;
(void)s2;
- (void)s1;
(void)this;
}),
@@ -387,3 +385,15 @@ void EX::advance_helper()
this->curr_instr->set_s1(s1);
this->status = OK;
}
+
+void EX::handle_divide(signed int &s1, signed int s2, bool is_mod)
+{
+ if (s2 == 0) {
+ // handle everything here
+ this->curr_instr->set_s1(MAX_INT);
+ this->status = OK;
+ throw HaltException();
+ } else {
+ s1 = (is_mod) ? s1 % s2 : s1 / s2;
+ }
+}
diff --git a/src/sim/id.cc b/src/sim/id.cc
index 37c6773..d10d695 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -86,7 +86,7 @@ void ID::get_instr_fields(
break;
case 0b10:
t = J;
- this->decode_J_type(s1, s2, s3);
+ this->decode_J_type(s1, s2, s3, m);
break;
case 0b11:
t = INV;
@@ -159,8 +159,10 @@ void ID::decode_I_type(
this->status = r1;
}
-void ID::decode_J_type(signed int &s1, signed int &s2, signed int &s3)
+void ID::decode_J_type(
+ signed int &s1, signed int &s2, signed int &s3, Mnemonic &m)
{
+ Response r1, r2;
unsigned int s0b, s1b;
s0b = REG_SIZE;
@@ -169,7 +171,33 @@ void ID::decode_J_type(signed int &s1, signed int &s2, signed int &s3)
s2 = GET_BITS_SIGN_EXTEND(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
- this->status = this->read_guard(*&s1);
+ switch (m) {
+ case PUSH:
+ s2 = s1; // source
+ s3 = 2; // stack pointer
+ s1 = -1; // increment amount
+ r1 = this->read_guard(s2);
+ r2 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ if (r1 == OK && r2 == OK) {
+ this->write_guard(s3); // we write the stack pointer
+ }
+ this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
+ break;
+ case POP:
+ s2 = s1; // destination
+ s3 = 2; // stack pointer
+ s1 = 1; // increment amount
+ r1 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ if (r1 == OK) {
+ this->write_guard(s2);
+ this->write_guard(s3); // we write the stack pointer
+ }
+ this->status = r1;
+ break;
+ default:
+ this->status = this->read_guard(*&s1);
+ }
+
}
std::vector<int> ID::stage_info()
diff --git a/src/sim/if.cc b/src/sim/if.cc
index 1223149..bab2608 100644
--- a/src/sim/if.cc
+++ b/src/sim/if.cc
@@ -37,13 +37,14 @@ void IF::advance_helper()
int i;
signed int bits;
- if (this->curr_instr == nullptr) {
+ if (this->curr_instr == nullptr && (this->is_pipelined || this->is_empty)) {
i = this->storage->read_word(this, this->pc, bits);
r = i ? OK : STALLED;
if (r == OK) {
this->curr_instr = new InstrDTO();
this->curr_instr->set_instr_bits(bits);
this->curr_instr->set_pc(this->pc);
+ this->is_empty = false;
}
}
}
diff --git a/src/sim/mm.cc b/src/sim/mm.cc
index a9a60c2..a02ca83 100644
--- a/src/sim/mm.cc
+++ b/src/sim/mm.cc
@@ -21,8 +21,8 @@ void MM::advance_helper()
this->status = STALLED;
break;
+ case PUSH:
case STORE:
- // TODO signed issues, we aren't wrapping addresses
i = this->storage->write_word(
this, this->curr_instr->get_s2(), this->curr_instr->get_s1());
this->status = i ? OK : STALLED;
@@ -31,6 +31,15 @@ void MM::advance_helper()
}
break;
+ case POP:
+ i = this->storage->read_word(this, this->curr_instr->get_s3(), data);
+ this->status = i ? OK : STALLED;
+ if (this->status == OK) {
+ this->curr_instr->set_s3(data);
+ } else
+ this->status = STALLED;
+ break;
+
default:
this->status = OK;
}
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 7df1dba..9528e4b 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -17,6 +17,7 @@ std::deque<signed int> Stage::checked_out;
unsigned int Stage::pc;
Storage *Stage::storage;
bool Stage::is_pipelined;
+bool Stage::is_empty;
int Stage::clock_cycle;
bool Stage::get_condition(CC c) { return (this->gprs[3] >> c) & 1; }
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index 4e6b2b0..c62468c 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -28,9 +28,17 @@ void WB::write_handler()
throw std::runtime_error("instruction tried to pop a register out of "
"an empty queue during writeback.");
+ if (this->curr_instr->get_mnemonic() == POP) {
+ // POP performs a second register write
+ reg = this->checked_out.front();
+ this->checked_out.pop_front();
+ this->store_register(reg, this->curr_instr->get_s3());
+ }
+
this->checked_out.pop_front();
reg = this->curr_instr->get_checked_out();
this->store_register(reg, this->curr_instr->get_s1());
+
}
void WB::jump_handler()