From eaa87e9fcd90c00d6261cbdb854efb7a09467f1d Mon Sep 17 00:00:00 2001 From: bd Date: Thu, 27 Mar 2025 20:30:18 -0400 Subject: Instr, InstrDTO gets/sets, other structures required for decode --- inc/instrDTO.h | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'inc/instrDTO.h') diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 86cec05..7f2c688 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -1,5 +1,7 @@ #ifndef INSTRDTO_H #define INSTRDTO_H +#include +#include class InstrDTO { @@ -14,26 +16,82 @@ class InstrDTO * @return if_cycle */ int get_if_cycle(); + /** + * @return id_cycle + */ + int get_id_cycle(); /** * @return instr_bits */ signed int get_instr_bits(); + /** + * @return s1 + */ + signed int get_s1(); + /** + * @return s2 + */ + signed int get_s2(); + /** + * @return s3 + */ + signed int get_s3(); + /** + * @return the string representation of oper. + */ + std::string get_oper_name(); /** * @param if_cycle */ void set_if_cycle(int); + /** + * @param id_cycle + */ + void set_id_cycle(int); /** * @param instr_bits */ void set_instr_bits(signed int); + /** + * @param s1 + */ + void set_s1(signed int); + /** + * @param s2 + */ + void set_s2(signed int); + /** + * @param s3 + */ + void set_s3(signed int); private: /** - * The current clock cycle. + * The clock cycle this instruction finished being fetched. */ int if_cycle; + /** + * The clock cycle this instruction finished being identified. + */ + int id_cycle; + /** + * The raw bits encoding the instruction. + */ signed int instr_bits; + /** + * Slots in this instruction, for storing temporary registers, immediates, + * or other. + * Some instruction types may use these differently. + * The `oper` function is in charge of knowing how to parse these. + */ + signed int s1; + signed int s2; + signed int s3; + /** + * The operation to be conducted during the execute phase. + */ + std::function instr; }; #endif /* INSTRDTO_H_INCLUDED */ -- cgit v1.2.3 From 043c2566c112f0d913c52aa80c9fcc4da5fb11ae Mon Sep 17 00:00:00 2001 From: bd Date: Thu, 27 Mar 2025 20:47:44 -0400 Subject: Use an unordered map to record pipe stage history on instructions --- inc/instrDTO.h | 22 ++++++++-------------- src/sim/if.cc | 2 +- src/sim/instrDTO.cc | 11 +++-------- tests/if.cc | 6 +++--- 4 files changed, 15 insertions(+), 26 deletions(-) (limited to 'inc/instrDTO.h') diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 7f2c688..2a6ab1f 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -2,6 +2,8 @@ #define INSTRDTO_H #include #include +#include +#include "accessor.h" class InstrDTO { @@ -13,9 +15,9 @@ class InstrDTO ~InstrDTO() = default; /** - * @return if_cycle + * @return hist entry for Accessor */ - int get_if_cycle(); + int get_time_of(Accessor); /** * @return id_cycle */ @@ -42,13 +44,9 @@ class InstrDTO std::string get_oper_name(); /** - * @param if_cycle + * @param set hist key */ - void set_if_cycle(int); - /** - * @param id_cycle - */ - void set_id_cycle(int); + void set_time_of(Accessor, int); /** * @param instr_bits */ @@ -68,13 +66,9 @@ class InstrDTO private: /** - * The clock cycle this instruction finished being fetched. - */ - int if_cycle; - /** - * The clock cycle this instruction finished being identified. + * The clock cycle each stage finished an operation. */ - int id_cycle; + std::unordered_map hist; /** * The raw bits encoding the instruction. */ diff --git a/src/sim/if.cc b/src/sim/if.cc index f5a2bb9..559ad2e 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -14,7 +14,7 @@ Response IF::advance(InstrDTO &i) r = this->storage->read_word(this->id, this->pc, bits); if (r == OK) { ++this->pc; - i.set_if_cycle(this->clock_cycle); + i.set_time_of(this->id, this->clock_cycle); i.set_instr_bits(bits); } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index 4e24d4e..7864eb4 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -1,18 +1,15 @@ #include "instrDTO.h" +#include "accessor.h" InstrDTO::InstrDTO() { - this->if_cycle = 0; - this->id_cycle = 0; this->instr_bits = 0; this->s1 = 0; this->s2 = 0; this->s3 = 0; } -int InstrDTO::get_if_cycle() { return this->if_cycle; } - -int InstrDTO::get_id_cycle() { return this->id_cycle; } +int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; } signed int InstrDTO::get_instr_bits() { return this->instr_bits; } @@ -22,9 +19,7 @@ signed int InstrDTO::get_s2() { return this->s2; } signed int InstrDTO::get_s3() { return this->s3; } -void InstrDTO::set_if_cycle(int cycle) { this->if_cycle = cycle; } - -void InstrDTO::set_id_cycle(int cycle) { this->id_cycle = cycle; } +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; } diff --git a/tests/if.cc b/tests/if.cc index 5c1b645..3e68ac4 100644 --- a/tests/if.cc +++ b/tests/if.cc @@ -77,7 +77,7 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns single instuction", "[if_pipe]") expected_cycles = this->m_delay + this->c_delay + 2; this->fetch_through(instr); - CHECK(instr.get_if_cycle() == expected_cycles); + CHECK(instr.get_time_of(FETCH) == expected_cycles); REQUIRE(instr.get_instr_bits() == this->p[0]); } @@ -89,12 +89,12 @@ TEST_CASE_METHOD(IFPipeFixture, "fetch returns two instuctions", "[if_pipe]") expected_cycles = this->m_delay + this->c_delay + 2; this->fetch_through(instr); - CHECK(instr.get_if_cycle() == expected_cycles); + CHECK(instr.get_time_of(FETCH) == expected_cycles); REQUIRE(instr.get_instr_bits() == this->p[0]); expected_cycles += this->c_delay + 1; this->fetch_cache(instr); - CHECK(instr.get_if_cycle() == expected_cycles); + CHECK(instr.get_time_of(FETCH) == expected_cycles); REQUIRE(instr.get_instr_bits() == this->p[1]); } -- cgit v1.2.3 From 9793bf119cc6314e264bdfc9e98bc27c81db0adb Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 29 Mar 2025 12:30:54 -0400 Subject: Add implementation functions for checking out a register. --- inc/instrDTO.h | 21 ++++++++++++-------- inc/response.h | 1 + inc/stage.h | 40 +++++++++++++++++++++++++++++++++++++- src/sim/id.cc | 37 ++++++++++++----------------------- src/sim/instrDTO.cc | 4 ++++ src/sim/stage.cc | 53 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/utils/response.cc | 2 +- 7 files changed, 120 insertions(+), 38 deletions(-) (limited to 'inc/instrDTO.h') diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 2a6ab1f..77a223e 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -1,9 +1,10 @@ #ifndef INSTRDTO_H #define INSTRDTO_H -#include +#include "accessor.h" +#include "instr.h" #include +#include #include -#include "accessor.h" class InstrDTO { @@ -39,9 +40,9 @@ class InstrDTO */ signed int get_s3(); /** - * @return the string representation of oper. + * @return the mnemonic of the instruction */ - std::string get_oper_name(); + Mnemonic get_mnemonic(); /** * @param set hist key @@ -63,6 +64,10 @@ class InstrDTO * @param s3 */ void set_s3(signed int); + /** + * @param the mnemonic of the instruction + */ + void set_mnemonic(Mnemonic); private: /** @@ -82,10 +87,10 @@ class InstrDTO signed int s1; signed int s2; signed int s3; - /** - * The operation to be conducted during the execute phase. - */ - std::function instr; + /** + * The mnemonic of the operation. + */ + Mnemonic mnemonic; }; #endif /* INSTRDTO_H_INCLUDED */ diff --git a/inc/response.h b/inc/response.h index 6cd6678..05e9352 100644 --- a/inc/response.h +++ b/inc/response.h @@ -6,6 +6,7 @@ enum Response { OK, WAIT, BLOCKED, + STALLED, }; std::ostream &operator<<(std::ostream &os, Response r); diff --git a/inc/stage.h b/inc/stage.h index f6bad41..0348263 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -1,11 +1,12 @@ #ifndef STAGE_H #define STAGE_H +#include "accessor.h" #include "definitions.h" #include "instrDTO.h" #include "response.h" #include "storage.h" -#include "accessor.h" #include +#include class Stage { @@ -27,6 +28,16 @@ class Stage virtual Response advance(InstrDTO &i) = 0; protected: + /** + * Facilitates register checkout. + * It does this by checking that the register passed in is not currently + * checked out. If true, then replaces r with the value of the register and + * returns OK. If false, returns STALLED. + * + * @param the registers number, to be dereferenced. + * @return OK if `r` is not checked out, STALLED otherwise. + */ + Response check_out(unsigned int &r); /** * The name of the pipeline stage. */ @@ -59,6 +70,33 @@ class Stage * The current clock cycle. */ static int clock_cycle; + + private: + /** + * Helper for `check_out`. + * Returns true if r are not checked out, false otherwise. + * @param a list of register numbers. + * @return true if registers are not in checked_out, false otherwise. + */ + bool is_checked_out(unsigned int r); + /** + * Helper for `check_out`. + * Checks out a single register, and places it in checked_out. + * @param a register number. + * @return the value in the register. + */ + signed int check_out_register(unsigned int r); + // TODO fix this comment after writeback stage + /** + * Helper for `check_out_register` + * @param the register number. + * @return the value in the associated register. + */ + signed int dereference_register(unsigned int r); + /** + * The set of registers currently checked out. + */ + static std::set checked_out; }; #endif /* STAGE_H_INCLUDED */ diff --git a/src/sim/id.cc b/src/sim/id.cc index c6e42d5..e9c48df 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -5,13 +5,20 @@ #include "logger.h" #include "response.h" #include "stage.h" -#include "utils.h" - -static Logger *global_log = Logger::getInstance(); ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; } -Response ID::advance(InstrDTO &i) { Response r; } +Response ID::advance(InstrDTO &i) +{ + Response r; + signed int s1, s2, s3; + Mnemonic m; + + s1 = i.get_instr_bits(); + + get_instr_fields(s1, s2, s3, m); + return r; +} // TODO this function is ugly void ID::get_instr_fields( @@ -53,30 +60,10 @@ void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m) opcode_size = (type == 0b0) ? R_OPCODE_SIZE : OPCODE_SIZE; opcode = GET_MID_BITS(raw, TYPE_SIZE, TYPE_SIZE + opcode_size); try { - m = instr::mnemonic_map.at((opcode << 2) + type); + m = instr::mnemonic_map.at((opcode << TYPE_SIZE) + type); } catch (std::out_of_range const &) { m = NOP; } raw = (unsigned int)raw >> (TYPE_SIZE + opcode_size); } - -Response ID::dereference_register(signed int &v) -{ - Response r; - r = OK; - - if (v < 0 || v >= GPR_NUM + V_NUM) { - global_log->log( - ERROR, string_format( - "instruction tried to access register %d, which does " - "not exist", - v)); - exit(EXIT_FAILURE); - } else if (v >= GPR_NUM) - v = this->vrs[v % GPR_NUM]; - else - v = this->gprs[v]; - - return r; -} diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index 7864eb4..7418033 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -19,6 +19,8 @@ signed int InstrDTO::get_s2() { return this->s2; } signed int InstrDTO::get_s3() { return this->s3; } +Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } + 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; } @@ -28,3 +30,5 @@ void InstrDTO::set_s1(signed int s) { this->s1 = s; } void InstrDTO::set_s2(signed int s) { this->s2 = s; } void InstrDTO::set_s3(signed int s) { this->s3 = s; } + +void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; } diff --git a/src/sim/stage.cc b/src/sim/stage.cc index 560cc41..8d9dfc0 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -1,12 +1,59 @@ #include "stage.h" +#include "utils.h" +#include +#include -Stage::Stage(Stage *next) { - this->next = next; -} +static Logger *global_log = Logger::getInstance(); + +Stage::Stage(Stage *next) { this->next = next; } std::array Stage::gprs; std::array Stage::vrs; +std::set Stage::checked_out; unsigned int Stage::pc; Storage *Stage::storage; bool Stage::is_pipelined; int Stage::clock_cycle; + +Response Stage::check_out(unsigned int &v) +{ + Response r; + if (this->is_checked_out(v)) + r = STALLED; + else { + r = OK; + v = this->check_out_register(v); + } + return r; +} + +bool Stage::is_checked_out(unsigned int r) +{ + return this->checked_out.find(r) != this->checked_out.end(); +} + +signed int Stage::check_out_register(unsigned int v) +{ + signed int r; + this->checked_out.insert(v); + + r = this->dereference_register(v); + return r; +} + +signed int Stage::dereference_register(unsigned int v) +{ + signed int r; + + if (v >= GPR_NUM + V_NUM) { + global_log->log( + ERROR, string_format( + "instruction tried to access register %d, which does " + "not exist", + v)); + exit(EXIT_FAILURE); + } + + r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[v]; + return r; +} diff --git a/src/utils/response.cc b/src/utils/response.cc index def6578..3d6e439 100644 --- a/src/utils/response.cc +++ b/src/utils/response.cc @@ -3,6 +3,6 @@ std::ostream &operator<<(std::ostream &os, Response r) { - const std::string nameR[] = {"OK", "WAIT", "BLOCKED"}; + const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; return os << nameR[r]; } -- cgit v1.2.3