diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/controller.cc | 16 | ||||
-rw-r--r-- | src/sim/ex.cc | 22 | ||||
-rw-r--r-- | src/sim/id.cc | 34 | ||||
-rw-r--r-- | src/sim/if.cc | 3 | ||||
-rw-r--r-- | src/sim/mm.cc | 11 | ||||
-rw-r--r-- | src/sim/stage.cc | 1 | ||||
-rw-r--r-- | src/sim/wb.cc | 8 |
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() |