diff options
Diffstat (limited to 'src/sim')
-rw-r--r-- | src/sim/controller.cc | 5 | ||||
-rw-r--r-- | src/sim/dum.cc | 8 | ||||
-rw-r--r-- | src/sim/ex.cc | 70 | ||||
-rw-r--r-- | src/sim/id.cc | 30 | ||||
-rw-r--r-- | src/sim/if.cc | 5 | ||||
-rw-r--r-- | src/sim/instrDTO.cc | 7 | ||||
-rw-r--r-- | src/sim/mm.cc | 44 | ||||
-rw-r--r-- | src/sim/stage.cc | 53 | ||||
-rw-r--r-- | src/sim/wb.cc | 82 |
9 files changed, 198 insertions, 106 deletions
diff --git a/src/sim/controller.cc b/src/sim/controller.cc index 7e24b3d..cf8d02d 100644 --- a/src/sim/controller.cc +++ b/src/sim/controller.cc @@ -9,6 +9,7 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined) this->storage = storage; this->is_pipelined = is_pipelined; this->pc = 0x0; + this->checked_out = {}; this->gprs = {0}; // grant side-door access this->id = SIDE; @@ -37,9 +38,11 @@ InstrDTO *Controller::advance(Response p) InstrDTO *r; r = this->next->advance(p); ++this->clock_cycle; + return r; } -void Controller::advance_helper() { +void Controller::advance_helper() +{ // TODO: check halt condition and call UI to refresh } diff --git a/src/sim/dum.cc b/src/sim/dum.cc index dd16660..76d4acd 100644 --- a/src/sim/dum.cc +++ b/src/sim/dum.cc @@ -9,13 +9,12 @@ DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; } InstrDTO *DUM::advance(Response p) { - InstrDTO *r = curr_instr; + InstrDTO *r = nullptr; - this->advance_helper(); - if (this->status == OK && p == OK) { + if (this->curr_instr && p == WAIT) { this->curr_instr->set_time_of(this->id, this->clock_cycle); r = new InstrDTO(*this->curr_instr); - delete curr_instr; + delete this->curr_instr; curr_instr = nullptr; } @@ -27,5 +26,4 @@ void DUM::advance_helper() {} void DUM::set_curr_instr(InstrDTO *d) { this->curr_instr = d; - this->status = OK; } diff --git a/src/sim/ex.cc b/src/sim/ex.cc index f22adc0..b6f8a1d 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -4,11 +4,12 @@ #include "instrDTO.h" #include "response.h" #include "stage.h" +#include "utils.h" #include <unordered_map> // clang-format off #define INIT_INSTRUCTION(mnemonic, body) \ - {mnemonic, [this](signed int &s1, signed int s2, signed int s3) { \ + {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \ body; \ }} // clang-format on @@ -23,6 +24,7 @@ EX::EX(Stage *stage) : Stage(stage) ADD, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -31,6 +33,7 @@ EX::EX(Stage *stage) : Stage(stage) SUB, { s1 = s1 - s2; + (void)pc; (void)s3; (void)this; }), @@ -39,6 +42,7 @@ EX::EX(Stage *stage) : Stage(stage) MUL, { s1 = s1 * s2; + (void)pc; (void)s3; (void)this; }), @@ -47,6 +51,7 @@ EX::EX(Stage *stage) : Stage(stage) QUOT, { s1 = s1 / s2; + (void)pc; (void)s3; (void)this; }), @@ -55,6 +60,7 @@ EX::EX(Stage *stage) : Stage(stage) REM, { s1 = s1 % s2; + (void)pc; (void)s3; (void)this; }), @@ -63,6 +69,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTR, { s1 = s1 >> s2; + (void)pc; (void)s3; (void)this; }), @@ -71,6 +78,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTL, { s1 = s1 << s2; + (void)pc; (void)s3; (void)this; }), @@ -79,6 +87,7 @@ EX::EX(Stage *stage) : Stage(stage) AND, { s1 = s1 & s2; + (void)pc; (void)s3; (void)this; }), @@ -87,6 +96,7 @@ EX::EX(Stage *stage) : Stage(stage) OR, { s1 = s1 | s2; + (void)pc; (void)s3; (void)this; }), @@ -95,6 +105,7 @@ EX::EX(Stage *stage) : Stage(stage) NOT, { s1 = ~s1; + (void)pc; (void)s3; (void)s2; (void)this; @@ -104,6 +115,7 @@ EX::EX(Stage *stage) : Stage(stage) XOR, { s1 = s1 ^ s2; + (void)pc; (void)s3; (void)this; }), @@ -111,6 +123,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ADDV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -120,6 +133,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( SUBV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -129,6 +143,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( MULV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -138,6 +153,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( DIVV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -151,12 +167,14 @@ EX::EX(Stage *stage) : Stage(stage) : this->set_condition(GT, false); (s1 == s2) ? this->set_condition(EQ, true) : this->set_condition(EQ, false); + (void)pc; (void)s3; }), INIT_INSTRUCTION( CEV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -168,6 +186,7 @@ EX::EX(Stage *stage) : Stage(stage) LOAD, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -175,6 +194,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( LOADV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -185,6 +205,7 @@ EX::EX(Stage *stage) : Stage(stage) ADDI, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -193,6 +214,7 @@ EX::EX(Stage *stage) : Stage(stage) SUBI, { s1 = s1 - s3; + (void)pc; (void)s2; (void)this; }), @@ -201,6 +223,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTRI, { s1 = s1 >> s3; + (void)pc; (void)s2; (void)this; }), @@ -209,6 +232,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTLI, { s1 = s1 << s3; + (void)pc; (void)s2; (void)this; }), @@ -217,6 +241,7 @@ EX::EX(Stage *stage) : Stage(stage) ANDI, { s1 = s1 & s3; + (void)pc; (void)s2; (void)this; }), @@ -225,6 +250,7 @@ EX::EX(Stage *stage) : Stage(stage) ORI, { s1 = s1 | s3; + (void)pc; (void)s2; (void)this; }), @@ -233,6 +259,7 @@ EX::EX(Stage *stage) : Stage(stage) XORI, { s1 = s1 ^ s3; + (void)pc; (void)s2; (void)this; }), @@ -241,6 +268,7 @@ EX::EX(Stage *stage) : Stage(stage) STORE, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -248,6 +276,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( STOREV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -259,6 +288,7 @@ EX::EX(Stage *stage) : Stage(stage) JMP, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -266,7 +296,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( JRL, { - s1 = this->pc + s2; + s1 = pc + s2; (void)s3; (void)this; }), @@ -275,6 +305,7 @@ EX::EX(Stage *stage) : Stage(stage) JAL, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -282,34 +313,39 @@ 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(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(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(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(pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( PUSH, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -319,6 +355,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( POP, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -329,6 +366,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( NOP, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -340,19 +378,17 @@ EX::EX(Stage *stage) : Stage(stage) void EX::advance_helper() { signed int s1, s2, s3; + unsigned int pc; Mnemonic m; - // it may be good to ensure we are not doing - // work that has already been done - if (this->curr_instr) { - m = this->curr_instr->get_mnemonic(); - s1 = this->curr_instr->get_s1(); - s2 = this->curr_instr->get_s2(); - s3 = this->curr_instr->get_s3(); + m = this->curr_instr->get_mnemonic(); + s1 = this->curr_instr->get_s1(); + s2 = this->curr_instr->get_s2(); + s3 = this->curr_instr->get_s3(); + pc = this->curr_instr->get_pc(); - this->instr_map[m](s1, s2, s3); + this->instr_map[m](s1, s2, s3, pc ); - this->curr_instr->set_s1(s1); - this->status = OK; - } + this->curr_instr->set_s1(s1); + this->status = OK; } diff --git a/src/sim/id.cc b/src/sim/id.cc index 0b75b64..0df26f4 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -48,11 +48,11 @@ void ID::advance_helper() Mnemonic m; Type t; - // it may be good to ensure we are not doing - // work that has already been done - if (this->curr_instr && this->curr_instr->get_mnemonic() == NONE) { + if (curr_instr->get_mnemonic() == NOP) + this->status = OK; + else { s1 = curr_instr->get_instr_bits(); - get_instr_fields(s1, s2, s3, m ,t); + get_instr_fields(s1, s2, s3, m, t); if (this->status == OK) { curr_instr->set_s1(s1); curr_instr->set_s2(s2); @@ -63,7 +63,8 @@ void ID::advance_helper() } } -void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) +void ID::get_instr_fields( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) { unsigned int type; this->split_instr(s1, type, m); @@ -75,11 +76,11 @@ void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemon break; case 0b01: t = I; - this->decode_I_type(s1, s2, s3); + this->decode_I_type(s1, s2, s3, m); break; case 0b10: t = J; - this->decode_J_type(s1, s2); + this->decode_J_type(s1, s2, s3); break; case 0b11: t = INV; @@ -106,9 +107,11 @@ void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3) this->status = (r1 == OK && r2 == OK) ? OK : STALLED; } -void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3) +void ID::decode_I_type( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) { unsigned int s0b, s1b, s2b; + Response r1; s0b = REG_SIZE; s1b = s0b + REG_SIZE; @@ -117,16 +120,21 @@ void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3) s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); - this->status = this->read_guard(s1); - this->write_guard(s2); + r1 = this->read_guard(s1); + if (m != STORE && m != STOREV) { + this->status = r1; + this->write_guard(s2); + } else + this->status = (this->read_guard(s2) == OK && r1 == OK) ? OK : STALLED; } -void ID::decode_J_type(signed int &s1, signed int &s2) +void ID::decode_J_type(signed int &s1, signed int &s2, signed int &s3) { unsigned int s0b, s1b; s0b = REG_SIZE; s1b = WORD_SPEC; + s3 = 0; s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); diff --git a/src/sim/if.cc b/src/sim/if.cc index fa8f6c2..85fb27f 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -11,14 +11,13 @@ InstrDTO *IF::advance(Response p) InstrDTO *r = nullptr; this->advance_helper(); - if (this->curr_instr != nullptr && p == OK) { + if (this->curr_instr != nullptr && p == WAIT) { // mutual consent ++this->pc; this->curr_instr->set_time_of(this->id, this->clock_cycle); r = new InstrDTO(*this->curr_instr); delete curr_instr; curr_instr = nullptr; - this->status = STALLED; } return r; @@ -32,9 +31,9 @@ void IF::advance_helper() if (this->curr_instr == nullptr) { r = this->storage->read_word(this->id, this->pc, bits); if (r == OK) { - this->status = r; this->curr_instr = new InstrDTO(); this->curr_instr->set_instr_bits(bits); + this->curr_instr->set_pc(this->pc); } } } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index b33c26b..aa49b7e 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -7,8 +7,9 @@ InstrDTO::InstrDTO() this->s1 = 0; this->s2 = 0; this->s3 = 0; - this->mnemonic = NONE; + this->mnemonic = ADD; this->type = INV; + this->pc = 0; } int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; } @@ -25,6 +26,8 @@ Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } Type InstrDTO::get_type() { return this->type; } +unsigned int InstrDTO::get_pc() { return this->pc; } + void InstrDTO::set_time_of(Accessor a, int i) { this->hist[a] = i; } void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } @@ -38,3 +41,5 @@ void InstrDTO::set_s3(signed int s) { this->s3 = s; } void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; } void InstrDTO::set_type(Type t) { this->type = t; } + +void InstrDTO::set_pc(unsigned int pc) { this->pc = pc; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc index cd85056..07a362b 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -4,26 +4,32 @@ #include "response.h" #include "stage.h" -MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } +MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } -void MM::advance_helper() { - Response r; +void MM::advance_helper() +{ signed int data; - if(this->curr_instr){ - if (this->curr_instr->get_mnemonic() == LOAD) { - r = this->storage->read_word(this->id, this->curr_instr->get_s1(), data); - if(r == OK){ - this->status = OK; - this->curr_instr->set_s2(data); - } - } else if (this->curr_instr->get_mnemonic() == STORE) { - r = this->storage->write_word(this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); - if(r == OK){ - this->status = OK; - } - } else { - // Mem has no work so just forward the instruction to WB - this->status = OK; + + switch (this->curr_instr->get_mnemonic()) { + case LOAD: + this->status = this->storage->read_word( + this->id, this->curr_instr->get_s1(), data); + if (this->status == OK) { + this->curr_instr->set_s1(data); + } else + this->status = STALLED; + break; + + case STORE: + // TODO signed issues, we aren't wrapping addresses + this->status = this->storage->write_word( + this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + if (this->status != OK) { + this->status = STALLED; } - } + break; + + default: + this->status = OK; + } } diff --git a/src/sim/stage.cc b/src/sim/stage.cc index be69d77..24bdf75 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -7,8 +7,7 @@ Stage::Stage(Stage *next) { this->next = next; this->curr_instr = nullptr; - this->status = OK; - this->checked_out = {}; + this->status = WAIT; } Stage::~Stage() { delete this->next; }; @@ -21,32 +20,30 @@ Storage *Stage::storage; bool Stage::is_pipelined; int Stage::clock_cycle; -bool Stage::get_condition(CC c) { - return (this->gprs[3] >> c) & 1; -} - -void Stage::set_pc(unsigned int pc) { - this->pc = pc; -} +bool Stage::get_condition(CC c) { return (this->gprs[3] >> c) & 1; } InstrDTO *Stage::advance(Response p) { InstrDTO *r = nullptr; + InstrDTO *s = nullptr; Response n; - this->advance_helper(); - if (this->status == OK && this->curr_instr != nullptr && p == 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); r = new InstrDTO(*this->curr_instr); delete curr_instr; curr_instr = nullptr; - this->status = STALLED; + this->status = WAIT; } - n = (p != OK || this->status != OK) ? STALLED : OK; - // the power of consent - this->curr_instr = this->next->advance(n); + n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; + s = this->next->advance(n); + if (s) + this->curr_instr = s; return r; } @@ -73,16 +70,34 @@ 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) != this->checked_out.end(); } -void Stage::squash(){ - this->curr_instr->set_mnemonic(NOP); - this->status = OK; - if(this->next){ +void Stage::squash() +{ + if (curr_instr) { + this->curr_instr->set_mnemonic(NOP); + this->status = OK; + } + if (this->next) { this->next->squash(); } } diff --git a/src/sim/wb.cc b/src/sim/wb.cc index ac47f25..01768e8 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -6,34 +6,56 @@ WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } -void WB::advance_helper() { - if(this -> curr_instr) { - 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(); - } - } - } - this->status = OK; +void WB::advance_helper() +{ + 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); } |