diff options
author | Siddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com> | 2025-05-11 11:51:15 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-11 11:51:15 -0400 |
commit | a35eb451889f0efa99ff7fe1c0a3a76afd5e7ad5 (patch) | |
tree | 44205b454c11a2d98711cd3226b4828e12a8479a /inc | |
parent | c7132dbc9c38ff766053bd9a0b72c68b23cd08d2 (diff) | |
parent | 6f4e9e0b914c3e68691a5d884cbad0b5813fcf18 (diff) |
Merge pull request #78 from bdunahu/bdunahu
cleanup/fix existing vector extension
Diffstat (limited to 'inc')
-rw-r--r-- | inc/ex.h | 76 | ||||
-rw-r--r-- | inc/id.h | 67 | ||||
-rw-r--r-- | inc/instr.h | 11 | ||||
-rw-r--r-- | inc/instrDTO.h | 17 | ||||
-rw-r--r-- | inc/stage.h | 6 | ||||
-rw-r--r-- | inc/wb.h | 9 |
6 files changed, 127 insertions, 59 deletions
@@ -23,36 +23,28 @@ #include <exception> #include <unordered_map> -#define ADDITION_OF_GUARD(a, b) \ - (b >= 0) && (a > MAX_INT - b) +#define ADDITION_OF_GUARD(a, b) (b >= 0) && (a > MAX_INT - b) -#define ADDITION_UF_GUARD(a, b) \ - (b < 0) && (a < (-(MAX_INT)-1) - b) +#define ADDITION_UF_GUARD(a, b) (b < 0) && (a < (-(MAX_INT)-1) - b) -#define SUBTRACTION_OF_GUARD(a, b) \ - (b < 0) && (a > MAX_INT + b) +#define SUBTRACTION_OF_GUARD(a, b) (b < 0) && (a > MAX_INT + b) -#define SUBTRACTION_UF_GUARD(a, b) \ - (b >= 0) && (a < (-(MAX_INT)-1) + b) +#define SUBTRACTION_UF_GUARD(a, b) (b >= 0) && (a < (-(MAX_INT)-1) + b) -#define MULTIPLICATION_OF_GUARD(a, b) \ - (b != 0) && \ - (((b > 0) && (a > 0) && (a > MAX_INT / b)) || \ - ((b < 0) && (a < 0) && (a < MAX_INT / b))) +#define MULTIPLICATION_OF_GUARD(a, b) \ + (b != 0) && (((b > 0) && (a > 0) && (a > MAX_INT / b)) || \ + ((b < 0) && (a < 0) && (a < MAX_INT / b))) -#define MULTIPLICATION_UF_GUARD(a, b) \ - (b != 0) && (b != -1) && \ - (((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \ - ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) +#define MULTIPLICATION_UF_GUARD(a, b) \ + (b != 0) && (b != -1) && \ + (((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \ + ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) -#define DIVISION_OF_GUARD(a, b) \ - ((a == -(MAX_INT) - 1) && (b == -1)) || (b == 0) +#define DIVISION_OF_GUARD(a, b) ((a == -(MAX_INT)-1) && (b == -1)) || (b == 0) class HaltException : public std::exception { - const char *what() const noexcept override { - return ""; - } + const char *what() const noexcept override { return ""; } }; class EX : public Stage @@ -63,19 +55,57 @@ class EX : public Stage * @param The next stage in the pipeline. * @return A newly allocated EX object. */ - using Stage::Stage; using Stage::advance; + using Stage::Stage; private: void advance_helper(); /** + * Handles operations involving three ints. + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param slot 3 + * @param the mnemonic + * @param the program counter + */ + void handle_int_operations( + signed int &s1, + signed int s2, + signed int s3, + Mnemonic m, + unsigned int pc); + /** + * Handles operations involving three vector registers. + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param slot 3 + * @param the mnemonic + * @param the vector length register + */ + void handle_vector_operations( + std::array<signed int, V_R_LIMIT> &s1, + std::array<signed int, V_R_LIMIT> s2, + Mnemonic m, + unsigned int v_len); + + /** + * Handles operations involving a single vector register. + * Currently, this is LOADV and STOREV + * @param slot 1, and later, the result of the mnemonic operation. + * @param slot 2 + * @param the mnemonic + * @param the vector length register + */ + void handle_i_vector_operations(signed int &s1, signed int s2, Mnemonic m); + /** * Wrapper for division functions, which detects HALT instructinos (division * by 0). * @param the numerator * @param the denominator * @param if the modulo operator should instead be used + * @return if the operation overflowed */ - void handle_divide(signed int &s1, signed int s2, bool is_mod); + bool handle_divide(signed int &s1, signed int s2, bool is_mod); }; #endif /* EX_H_INCLUDED */ @@ -25,35 +25,13 @@ class ID : public Stage { public: - using Stage::Stage; using Stage::advance; + using Stage::Stage; /* The following methods are made public so that they may be tested, and are * not to be called from outside classes during standard execution. */ - /** - * Facilitates register checkout and data hazard management. - * 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 read_guard(signed int &r); - /** - * Facilitates register checkout and data hazard management. - * Checks out a register and returns it. - * - * @param the registers number, to be dereferenced and checked out. - */ - void write_guard(signed int &r); - - Response read_vec_guard(signed int r, std::array<signed int, V_R_LIMIT> &v); - - void write_vec_guard(signed int r, std::array<signed int, V_R_LIMIT> &v); - Response set_vlen(); private: @@ -82,7 +60,7 @@ class ID : public Stage * @param the resulting third field, which varies per type. * @param the resulting mnemonic. */ - void get_instr_fields(signed int &s1); + void get_instr_fields(signed int instr_bits); void decode_R_type(signed int &s1); void decode_I_type(signed int &s1); void decode_J_type(signed int &s1); @@ -95,6 +73,47 @@ class ID : public Stage * @param the resulting type. */ void split_instr(signed int &raw, unsigned int &type, Mnemonic &m); + /** + * Facilitates register checkout and data hazard management. + * Checks out a register and returns it. + * + * @param the registers number, to be dereferenced and checked out. + */ + template <typename T> T write_guard(int v) + { + T r; + // these registers shouldn't be written. + if (v != 0 && v != 16) { + // keep track in the instrDTO for displaying to user and writeback + // keep track in checked_out so we can still access this + // information! + this->checked_out.push_back(v); + this->curr_instr->checked_out = v; + } + r = this->dereference_register<T>(v); + return r; + } + /** + * Facilitates register checkout and data hazard management. + * It does this by checking that the register passed in is not currently + * checked out. If true, then sets `result' with the value of the register + * and returns OK. If false, returns STALLED. + * + * @param the registers number + * @param the dereferenced register value + * @return OK if `reg` is not checked out, STALLED otherwise. + */ + template <typename T> Response read_guard(int reg, T &result) + { + Response response; + if (this->is_checked_out(reg)) + response = STALLED; + else { + response = OK; + result = this->dereference_register<T>(reg); + } + return response; + } }; #endif /* ID_H_INCLUDED */ diff --git a/inc/instr.h b/inc/instr.h index 98a1f0e..0c49a79 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -61,9 +61,20 @@ enum Mnemonic { NOP, }; +enum FieldType { + SI_INT, + R_VECT, + I_VECT, +}; + namespace instr { extern const std::unordered_map<unsigned int, Mnemonic> mnemonic_map; +/** + * @param a mnemonic + * @return an enum representing the types of the decoded instruction fields. + */ +FieldType get_field_types(Mnemonic m); } // namespace instr #endif /* INSTR_H_INCLUDED */ diff --git a/inc/instrDTO.h b/inc/instrDTO.h index f3d4597..ccc6ed9 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -19,7 +19,8 @@ #define INSTRDTO_H #include "instr.h" #include "pipe_spec.h" -#include<array> +#include <array> + struct U_INT_TYPE { signed int slot_one; @@ -33,10 +34,10 @@ struct V_TYPE { std::array<signed int, V_R_LIMIT> slot_three; }; -struct LOAD_STORE_V_TYPE{ - signed int base_addr; - signed int immediate; - std::array<signed int, V_R_LIMIT> vector_register; +struct VI_TYPE { + signed int slot_one; + signed int slot_two; + std::array<signed int, V_R_LIMIT> slot_three; }; struct InstrDTO { @@ -60,10 +61,14 @@ struct InstrDTO { * The register this instruction checks out. */ signed int checked_out; + /** + * The currently active union member. + */ + FieldType type; union { struct U_INT_TYPE integer; struct V_TYPE vector; - struct LOAD_STORE_V_TYPE load_store_vector; + struct VI_TYPE i_vector; } operands; }; diff --git a/inc/stage.h b/inc/stage.h index 4e0c252..834b941 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -83,10 +83,6 @@ class Stage */ static std::deque<signed int> checked_out; - bool is_vector_type(Mnemonic m); - - bool is_logical(Mnemonic m); - protected: /** * The function expected to do the majority of the work. @@ -140,7 +136,7 @@ class Stage } else if constexpr (std::is_same_v<T, std::array<signed int, V_R_LIMIT>>) { if (v < GPR_NUM || v >= GPR_NUM + V_NUM) { - throw std::out_of_range("Invalid vector register index"); + throw std::out_of_range("Invalid VRS index"); } return vrs[v % GPR_NUM]; } @@ -24,8 +24,8 @@ class WB : public Stage { public: - using Stage::Stage; using Stage::advance; + using Stage::Stage; private: void advance_helper() override; @@ -47,6 +47,13 @@ class WB : public Stage * STORE. */ bool should_jump(); + /** + * @return the vector register to be stored, obtained by copying the + * unfilled elements in the destination register to the source. This is + * required to ensure what is written back only changes VECTOR_LENGTH number + * of elements. + */ + std::array<signed int, V_R_LIMIT> copy_extra_vector_elements(); }; #endif /* WB_H_INCLUDED */ |