diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/ex.cc | 14 | ||||
-rw-r--r-- | src/sim/id.cc | 20 | ||||
-rw-r--r-- | src/sim/instrDTO.cc | 2 | ||||
-rw-r--r-- | src/sim/mm.cc | 1 | ||||
-rw-r--r-- | src/sim/stage.cc | 25 | ||||
-rw-r--r-- | src/sim/wb.cc | 75 |
6 files changed, 93 insertions, 44 deletions
diff --git a/src/sim/ex.cc b/src/sim/ex.cc index 3d95917..ec4c47f 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -4,6 +4,7 @@ #include "instrDTO.h" #include "response.h" #include "stage.h" +#include "utils.h" #include <unordered_map> // clang-format off @@ -185,6 +186,7 @@ EX::EX(Stage *stage) : Stage(stage) ADDI, { s1 = s1 + s3; + std::cout << "= " << s2 << std::endl; (void)s2; (void)this; }), @@ -282,28 +284,32 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( BEQ, { - (this->get_condition(EQ)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(EQ)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BGT, { - (this->get_condition(GT)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(GT)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BUF, { - (this->get_condition(UF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(UF)) ? s1 = wrap_address(this->pc) + s2 + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BOF, { - (this->get_condition(OF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(OF)) ? s1 = wrap_address(this->pc + s2) + : s1 = -1; (void)s3; }), diff --git a/src/sim/id.cc b/src/sim/id.cc index 4a55d04..ddac35b 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -48,14 +48,18 @@ void ID::advance_helper() Mnemonic m; Type t; - s1 = curr_instr->get_instr_bits(); - get_instr_fields(s1, s2, s3, m, t); - if (this->status == OK) { - curr_instr->set_s1(s1); - curr_instr->set_s2(s2); - curr_instr->set_s3(s3); - curr_instr->set_mnemonic(m); - curr_instr->set_type(t); + if (curr_instr->get_mnemonic() == NOP) + this->status = OK; + else { + s1 = curr_instr->get_instr_bits(); + get_instr_fields(s1, s2, s3, m, t); + if (this->status == OK) { + curr_instr->set_s1(s1); + curr_instr->set_s2(s2); + curr_instr->set_s3(s3); + curr_instr->set_mnemonic(m); + curr_instr->set_type(t); + } } } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index 28364b7..7324ba9 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -7,7 +7,7 @@ InstrDTO::InstrDTO() this->s1 = 0; this->s2 = 0; this->s3 = 0; - this->mnemonic = NOP; + this->mnemonic = ADD; this->type = INV; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc index c83ae7d..e29bf90 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -10,6 +10,7 @@ void MM::advance_helper() { signed int data; + std::cout << "mem" << this->curr_instr->get_s2() << std::endl; switch (this->curr_instr->get_mnemonic()) { case LOAD: this->status = this->storage->read_word( diff --git a/src/sim/stage.cc b/src/sim/stage.cc index 31d7d0d..b10a206 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -2,7 +2,6 @@ #include "utils.h" #include <array> #include <deque> -#include <iostream> Stage::Stage(Stage *next) { @@ -28,10 +27,12 @@ void Stage::set_pc(unsigned int pc) { this->pc = pc; } InstrDTO *Stage::advance(Response p) { InstrDTO *r = nullptr; + InstrDTO *s = nullptr; Response n; - if (this->curr_instr && this->status != OK) + if (this->curr_instr && this->status != OK) { this->advance_helper(); + } if (this->status == OK && p == WAIT && this->curr_instr) { // mutual consent this->curr_instr->set_time_of(this->id, this->clock_cycle); @@ -42,8 +43,9 @@ InstrDTO *Stage::advance(Response p) } n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; - // the power of consent - this->curr_instr = this->next->advance(n); + s = this->next->advance(n); + if (s) + this->curr_instr = s; return r; } @@ -70,6 +72,21 @@ signed int Stage::dereference_register(signed int v) return r; } +void Stage::store_register(signed int v, signed int d) +{ + if (v < 0 || v >= GPR_NUM + V_NUM) { + throw std::out_of_range(string_format( + "instruction tried to access register %d, which does " + "not exist", + v)); + } + + if (v >= GPR_NUM) + this->vrs[v % GPR_NUM] = d; + else + this->gprs[v] = d; +} + bool Stage::is_checked_out(signed int r) { return std::find(this->checked_out.begin(), this->checked_out.end(), r) != diff --git a/src/sim/wb.cc b/src/sim/wb.cc index 276d1d0..01768e8 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -8,33 +8,54 @@ WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } void WB::advance_helper() { - if (this->curr_instr->get_type() == R || - this->curr_instr->get_type() == I) { - if (this->checked_out.size() > 0) { - signed int reg = this->checked_out.front(); - this->checked_out.pop_front(); - if (reg >= GPR_NUM) { - // TODO: handle vector instructions - } else { - if (this->curr_instr->get_mnemonic() != STORE && - this->curr_instr->get_mnemonic() != STOREV) { - this->gprs[reg] = this->curr_instr->get_s1(); - } - } - } - } else if (this->curr_instr->get_type() == J) { - // TODO:handle push pop - // branch taken - if (this->pc != this->curr_instr->get_s1()) { - if (this->curr_instr->get_mnemonic() == JAL) { - // set link register to next instruction - this->gprs[1] = this->pc + 1; - } - this->pc = this->curr_instr->get_s1(); - // clear pending registers and squash pipeline - this->checked_out = {}; - this->next->squash(); - } + if (this->curr_instr->get_mnemonic() != NOP && + this->curr_instr->get_type() != INV) { + if (this->should_write()) + this->write_handler(); + else if (this->should_jump()) + this->jump_handler(); } this->status = OK; } + +void WB::write_handler() +{ + signed int reg; + + if (this->checked_out.size() < 1) + throw std::runtime_error("instruction tried to pop a register out of " + "an empty queue during writeback."); + + reg = this->checked_out.front(); + this->checked_out.pop_front(); + this->store_register(reg, this->curr_instr->get_s1()); +} + +void WB::jump_handler() +{ + if (this->curr_instr->get_s1() > 0) { + if (this->curr_instr->get_mnemonic() == JAL) + this->gprs[1] = this->pc + 1; + this->pc = this->curr_instr->get_s1(); + this->checked_out = {}; + this->next->squash(); + } +} + +bool WB::should_jump() +{ + Type t; + + t = this->curr_instr->get_type(); + return t == J; +} + +bool WB::should_write() +{ + Mnemonic m; + Type t; + + m = this->curr_instr->get_mnemonic(); + t = this->curr_instr->get_type(); + return (t == R || t == I) && (m != STORE && m != STOREV); +} |