diff options
author | Siddarth-Suresh <65844402+Siddarth-Suresh@users.noreply.github.com> | 2025-04-26 20:21:02 -0400 |
---|---|---|
committer | Siddarth-Suresh <65844402+Siddarth-Suresh@users.noreply.github.com> | 2025-04-26 20:21:02 -0400 |
commit | 41f612789f652654b5f2fa8c3fee4e348e2081b1 (patch) | |
tree | 386658b4231c6c1daa4f2f9769959d0934b2b44e | |
parent | 73633535288711de4850b9d9eec6326eb5de06c0 (diff) |
Initial vector extension changes
-rw-r--r-- | inc/ex.h | 7 | ||||
-rw-r--r-- | inc/id.h | 14 | ||||
-rw-r--r-- | inc/instrDTO.h | 5 | ||||
-rw-r--r-- | inc/pipe_spec.h | 2 | ||||
-rw-r--r-- | inc/stage.h | 60 | ||||
-rw-r--r-- | inc/vec.h | 44 | ||||
-rw-r--r-- | src/ex.cc | 587 | ||||
-rw-r--r-- | src/id.cc | 178 | ||||
-rw-r--r-- | src/stage.cc | 37 | ||||
-rw-r--r-- | src/vec.cc | 113 | ||||
-rw-r--r-- | src/wb.cc | 4 |
11 files changed, 406 insertions, 645 deletions
@@ -63,7 +63,7 @@ class EX : public Stage * @param The next stage in the pipeline. * @return A newly allocated EX object. */ - EX(Stage *next); + using Stage::Stage; using Stage::advance; private: @@ -81,11 +81,6 @@ class EX : public Stage * logic. * All instructions store the result into s1. */ - std::unordered_map< - Mnemonic, - std::function<void( - signed int &s1, signed int s2, signed int s3, unsigned int pc)>> - instr_map; }; #endif /* EX_H_INCLUDED */ @@ -50,6 +50,12 @@ class ID : public Stage */ 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(); + std::vector<int> stage_info() override; private: @@ -78,10 +84,10 @@ class ID : public Stage * @param the resulting third field, which varies per type. * @param the resulting mnemonic. */ - void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); - void decode_R_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); - void decode_I_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); - void decode_J_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); + void get_instr_fields(signed int &s1); + void decode_R_type(signed int &s1); + void decode_I_type(signed int &s1); + void decode_J_type(signed int &s1); /** * Helper for `get_instr_fields`. * Given a raw instruction, returns the mnemonic and type. diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 1402526..8f8e28e 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -18,6 +18,8 @@ #ifndef INSTRDTO_H #define INSTRDTO_H #include "instr.h" +#include "pipe_spec.h" +#include<array> struct U_INT_TYPE { signed int slot_one; @@ -26,6 +28,9 @@ struct U_INT_TYPE { }; struct V_TYPE { + std::array<signed int, V_R_LIMIT> slot_one; + std::array<signed int, V_R_LIMIT> slot_two; + std::array<signed int, V_R_LIMIT> slot_three; }; struct InstrDTO { diff --git a/inc/pipe_spec.h b/inc/pipe_spec.h index 7d65637..d8153af 100644 --- a/inc/pipe_spec.h +++ b/inc/pipe_spec.h @@ -80,6 +80,8 @@ */ #define CACHE_DELAY 1 +#define VECTOR_MEM_DELAY 10 + /** * Return the N least-significant bits from integer K using a bit mask * @param the integer to be parsed diff --git a/inc/stage.h b/inc/stage.h index 7dcb7b4..ae01723 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -82,6 +82,10 @@ 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. @@ -103,13 +107,63 @@ class Stage * @param the register number. * @param the value to store. */ - void store_register(signed int v, signed int d); + template <typename T> + void store_register(signed int v, T d) + { + // if (v < 0 || v >= GPR_NUM + V_NUM) { + // throw std::out_of_range( + // "instruction tried to access register which does not exist"); + // } + + // if (v >= GPR_NUM) + // this->vrs[v % GPR_NUM] = d; + // else + // this->gprs[v] = d; + + if constexpr (std::is_same_v<T, signed int>) { + if (v < 0 || v >= GPR_NUM) { + throw std::out_of_range("Invalid GPR index for storing scalar"); + } + gprs[v] = d; + } + 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 VR index for storing vector"); + } + vrs[v % GPR_NUM] = d; + } + } /** * Returns the value of the register corresponding to `v`. * @param the register number. * @return the value in the associated register. */ - signed int dereference_register(signed int v); + template <typename T> + T dereference_register(signed int v) + { + // signed int r; + + // if (v < 0 || v >= GPR_NUM + V_NUM) { + // throw std::out_of_range( + // "instruction tried to access register which does not exist"); + // } + + // r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[v]; + // return r; + + if constexpr (std::is_same_v<T, signed int>) { + if (v < 0 || v >= GPR_NUM) { + throw std::out_of_range("Invalid GPR index"); + } + return gprs[v]; + } + 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"); + } + return vrs[v % GPR_NUM]; + } + } /** * The shared pool of general-purpose integer registers. */ @@ -117,7 +171,7 @@ class Stage /** * The shared pool of general-purpose vector registers. */ - static std::array<signed int, V_NUM> vrs; + static std::array<std::array<signed int, V_R_LIMIT>, V_NUM> vrs; /** * The address of the currently executing instruction. */ diff --git a/inc/vec.h b/inc/vec.h deleted file mode 100644 index 68482d5..0000000 --- a/inc/vec.h +++ /dev/null @@ -1,44 +0,0 @@ -// vec.h -#ifndef VEC_H -#define VEC_H - -#include <iostream> -#include <vector> -#include <stdexcept> - -template<typename T> -class Vec { -private: - std::vector<T> data; - -public: - Vec() = default; - Vec(const std::vector<T>& values) : data(values) {} - - // Vector-Vector Operations - Vec<T> operator+(const Vec<T>& other) const; - Vec<T> operator-(const Vec<T>& other) const; - Vec<T> operator*(const Vec<T>& other) const; - Vec<T> operator/(const Vec<T>& other) const; - Vec<T> operator%(const Vec<T>& other) const; - - // Vector-Scalar Operations - Vec<T> operator+(T scalar) const; - Vec<T> operator-(T scalar) const; - Vec<T> operator*(T scalar) const; - Vec<T> operator/(T scalar) const; - Vec<T> operator%(T scalar) const; - - // Utility - void print() const; - size_t size() const { return data.size(); } - - // Friend scalar-vector operations - friend Vec<T> operator+(T scalar, const Vec<T>& vec) { return vec + scalar; } - friend Vec<T> operator-(T scalar, const Vec<T>& vec); - friend Vec<T> operator*(T scalar, const Vec<T>& vec) { return vec * scalar; } - friend Vec<T> operator/(T scalar, const Vec<T>& vec); - friend Vec<T> operator%(T scalar, const Vec<T>& vec); -}; - -#endif @@ -22,415 +22,204 @@ #include "stage.h" #include <unordered_map> -// clang-format off -#define INIT_INSTRUCTION(mnemonic, body) \ - {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \ - body; \ - }} -// clang-format on - -EX::EX(Stage *stage) : Stage(stage) -{ - instr_map = { - - /* R type instructions */ - INIT_INSTRUCTION( - ADD, - { - this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SUB, - { - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); - s1 = s1 - s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - MUL, - { - this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); - this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); - s1 = s1 * s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - QUOT, - { - this->handle_divide(s1, s2, false); - (void)pc; - (void)s3; - }), - - INIT_INSTRUCTION( - REM, - { - this->handle_divide(s1, s2, true); - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SFTR, - { - s1 = s1 >> s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SFTL, - { - s1 = s1 << s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - AND, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 & s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - OR, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 | s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - NOT, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = ~s1; - (void)pc; - (void)s3; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - XOR, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 ^ s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - ADDV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - SUBV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - MULV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - DIVV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - CMP, - { - (s1 > s2) ? this->set_condition(GT, true) - : 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; - (void)this; - }), - - /* I type instructions */ - INIT_INSTRUCTION( - LOAD, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - LOADV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - ADDI, - { - this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SUBI, - { - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); - s1 = s1 - s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SFTRI, - { - s1 = s1 >> s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SFTLI, - { - s1 = s1 << s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - ANDI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 & s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - ORI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 | s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - XORI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 ^ s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - STORE, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - STOREV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - /* J type instructions */ - INIT_INSTRUCTION( - JMP, - { - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - JRL, - { - s1 = pc + s2; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - JAL, - { - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - BEQ, - { - (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BGT, - { - (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BUF, - { - (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BOF, - { - (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - PUSH, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - POP, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - RET, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - /* NOP */ - INIT_INSTRUCTION( - NOP, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - }; -} +// Switch statements for each instruction void EX::advance_helper() { signed int s1, s2, s3; + std::array<signed int, V_R_LIMIT> v1, v2, v3; + signed int v_len; unsigned int pc; Mnemonic m; m = this->curr_instr->mnemonic; - s1 = this->curr_instr->operands.integer.slot_one; - s2 = this->curr_instr->operands.integer.slot_two; - s3 = this->curr_instr->operands.integer.slot_three; - pc = this->curr_instr->slot_B; - this->instr_map[m](s1, s2, s3, pc); + if(this->is_vector_type(m)) { + v1 = this->curr_instr->operands.vector.slot_one; + v2 = this->curr_instr->operands.vector.slot_two; + v3 = this->curr_instr->operands.vector.slot_three; + v_len = this->curr_instr->slot_A; + /*if(v_len == 0){ + //clear vector reg + v1.fill(0); + v2.fill(0); + v3.fill(0); + }*/ + } else{ + s1 = this->curr_instr->operands.integer.slot_one; + s2 = this->curr_instr->operands.integer.slot_two; + s3 = this->curr_instr->operands.integer.slot_three; + pc = this->curr_instr->slot_B; + } - this->curr_instr->operands.integer.slot_one = s1; + if(this->is_logical(m)) { + this->set_condition(OF, false); + this->set_condition(UF, false); + } + + switch(m) { + case ADD: + this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); + s1 = s1 + s2; + break; + + case SUB: + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); + s1 = s1 - s2; + break; + + case MUL: + this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); + this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); + s1 = s1 * s2; + break; + + case QUOT: + this->handle_divide(s1, s2, false); + break; + + case REM: + this->handle_divide(s1, s2, true); + break; + + case SFTR: + s1 = s1 >> s2; + break; + + case SFTL: + s1 = s1 << s2; + break; + + case AND: + s1 = s1 & s2; + break; + + case OR: + s1 = s1 | s2; + break; + + case XOR: + s1 = s1 ^ s2; + break; + + case NOT: + s1 = ~s1; + break; + + case CMP: + (s1 > s2) ? this->set_condition(GT, true) + : this->set_condition(GT, false); + (s1 == s2) ? this->set_condition(EQ, true) + : this->set_condition(EQ, false); + break; + + case ADDI: + this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); + s1 = s1 + s3; + break; + + case SUBI: + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); + s1 = s1 - s3; + break; + + case SFTRI: + s1 = s1 >> s3; + break; + + case SFTLI: + s1 = s1 << s3; + break; + + case ANDI: + s1 = s1 & s3; + break; + + case ORI: + s1 = s1 | s3; + break; + + case XORI: + s1 = s1 ^ s3; + break; + + case LOAD: + case STORE: + case PUSH: + case POP: + s1 = s1 + s3; + break; + + case JMP: + case JAL: + s1 = s1 + s2; + break; + + case JRL: + s1 = pc + s2; + break; + + case BEQ: + (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1; + break; + + case BGT: + (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1; + break; + + case BUF: + (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1; + break; + + case BOF: + (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1; + break; + + case ADDV: + if(v_len ==0){ + + } else { + for(int i=0;i<v_len;i++){ + this->set_condition(OF, ADDITION_OF_GUARD(v1[i],v2[i])); + this->set_condition(UF, ADDITION_UF_GUARD(v1[i],v2[i])); + v1[i] = v1[i] + v2[i]; + } + } + break; + case SUBV: + for(int i=0;i<v_len;i++){ + this->set_condition(OF, SUBTRACTION_OF_GUARD(v1[i],v2[i])); + this->set_condition(UF, SUBTRACTION_UF_GUARD(v1[i],v2[i])); + v1[i] = v1[i] - v2[i]; + } + break; + case MULV: + for(int i=0;i<v_len;i++){ + this->set_condition(OF, MULTIPLICATION_OF_GUARD(v1[i],v2[i])); + this->set_condition(UF, MULTIPLICATION_UF_GUARD(v1[i],v2[i])); + v1[i] = v1[i] * v2[i]; + } + break; + case DIVV: + for(int i=0;i<v_len;i++){ + this->handle_divide(v1[i],v2[i],false); + } + break; + case CEV: + case LOADV: + case STOREV: + break; + + case RET: + case NOP: + break; + + } + this->status = OK; } @@ -22,30 +22,26 @@ #include "response.h" #include "stage.h" -void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m) +Response ID::read_guard(signed int &v) { - unsigned int opcode, opcode_size; - - type = GET_LS_BITS(raw, TYPE_SIZE); - 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 << TYPE_SIZE) + type); - } catch (std::out_of_range const &) { - m = NOP; + Response r; + if (this->is_checked_out(v)) + r = STALLED; + else { + r = OK; + v = this->dereference_register<signed int>(v); } - - raw = (unsigned int)raw >> (TYPE_SIZE + opcode_size); + return r; } -Response ID::read_guard(signed int &v) +Response ID::read_vec_guard(signed int v, std::array<signed int, V_R_LIMIT> &vrs) { Response r; if (this->is_checked_out(v)) r = STALLED; else { r = OK; - v = this->dereference_register(v); + vrs = this->dereference_register<std::array<signed int, V_R_LIMIT>>(v); } return r; } @@ -59,54 +55,95 @@ void ID::write_guard(signed int &v) this->checked_out.push_back(v); this->curr_instr->checked_out = v; } - v = this->dereference_register(v); + v = this->dereference_register<signed int>(v); +} + +void ID::write_vec_guard(signed int v, std::array<signed int, V_R_LIMIT> &vrs){ + + // zero register shouldn't be written. + if (v != 0) { + // 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; + } + vrs = this->dereference_register<std::array<signed int, V_R_LIMIT>>(v); } void ID::advance_helper() { - signed int s1, s2, s3; - Mnemonic m; + signed int s1; - if (curr_instr->mnemonic == NOP) + if (this->curr_instr->mnemonic == NOP) this->status = OK; else { - s1 = curr_instr->slot_A; - get_instr_fields(s1, s2, s3, m); - if (this->status == OK) { - curr_instr->operands.integer.slot_one = s1; - curr_instr->operands.integer.slot_two = s2; - curr_instr->operands.integer.slot_three = s3; - curr_instr->mnemonic = m; - } + // instuction in bits in s1 + s1 = this->curr_instr->slot_A; + get_instr_fields(s1); } } -void ID::get_instr_fields( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +void ID::get_instr_fields(signed int &s1) { unsigned int type; + Mnemonic m; this->split_instr(s1, type, m); - + this->curr_instr->mnemonic = m; switch (type) { case 0b00: - this->decode_R_type(s1, s2, s3, m); + this->decode_R_type(s1); break; case 0b01: - this->decode_I_type(s1, s2, s3, m); + this->decode_I_type(s1); break; case 0b10: - this->decode_J_type(s1, s2, s3, m); + this->decode_J_type(s1); break; case 0b11: + // not defined, m = NOP this->status = OK; } } -void ID::decode_R_type( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m) +{ + unsigned int opcode, opcode_size; + + type = GET_LS_BITS(raw, TYPE_SIZE); + 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 << TYPE_SIZE) + type); + } catch (std::out_of_range const &) { + m = NOP; + } + + raw = (unsigned int)raw >> (TYPE_SIZE + opcode_size); +} + +Response ID::set_vlen(){ + signed int vlen_reg = 4; + Response r; + r = this->read_guard(vlen_reg); + vlen_reg = vlen_reg & 0xf; + if (r == OK){ + if (vlen_reg > V_R_LIMIT){ + this->curr_instr->slot_A = V_R_LIMIT; + } else { + this->curr_instr->slot_A = vlen_reg; + } + } + return r; +} + + + +void ID::decode_R_type(signed int &s1) { unsigned int s0b, s1b, s2b; + signed int s2, s3; Response r1, r2; + Response r3 = OK; s0b = REG_SIZE; s1b = s0b + REG_SIZE; @@ -115,46 +152,85 @@ void ID::decode_R_type( s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); - r1 = this->read_guard(s1); - r2 = this->read_guard(s2); - this->status = (r1 == OK && r2 == OK) ? OK : STALLED; + if(this->is_vector_type(this->curr_instr->mnemonic)){ + r1 = this->read_vec_guard(s1, this->curr_instr->operands.vector.slot_one); + r2 = this->read_vec_guard(s2, this->curr_instr->operands.vector.slot_two); + r3 = this->set_vlen(); + } else { + r1 = this->read_guard(s1); + this->curr_instr->operands.integer.slot_one = s1; + r2 = this->read_guard(s2); + this->curr_instr->operands.integer.slot_two = s2; + } - switch (m) { + this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED; + + switch (this->curr_instr->mnemonic) { case CMP: case CEV: break; + case ADDV: + case SUBV: + case MULV: + case DIVV: + if(this->status == OK){ + this->write_vec_guard(s3, this->curr_instr->operands.vector.slot_three); + } + break; default: if (this->status == OK) this->write_guard(s3); + this->curr_instr->operands.integer.slot_three = s3; } } -void ID::decode_I_type( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +void ID::decode_I_type(signed int &s1) { unsigned int s0b, s1b, s2b; + signed int s2, s3; Response r1, r2; + Response r3 = OK; s0b = REG_SIZE; s1b = s0b + REG_SIZE; s2b = WORD_SPEC - LINE_SPEC - OPCODE_SIZE; s3 = GET_BITS_SIGN_EXTEND(s1, s1b, s2b); - switch (m) { + switch (this->curr_instr->mnemonic) { case STORE: - case STOREV: s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); // both operands are read values r1 = this->read_guard(s1); + this->curr_instr->operands.integer.slot_one = s1; r2 = this->read_guard(s2); + this->curr_instr->operands.integer.slot_two = s2; this->status = (r1 == OK && r2 == OK) ? OK : STALLED; return; - case LOAD: + case STOREV: + s2 = GET_MID_BITS(s1, s0b, s1b); + s1 = GET_LS_BITS(s1, s0b); + + // both operands are read values + r1 = this->read_vec_guard(s1,this->curr_instr->operands.vector.slot_one); + r2 = this->read_vec_guard(s2,this->curr_instr->operands.vector.slot_two); + r3 = this->set_vlen(); + + this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED; + return; case LOADV: s2 = GET_LS_BITS(s1, s0b); s1 = GET_MID_BITS(s1, s0b, s1b); + r1 = this->read_vec_guard(s1, this->curr_instr->operands.vector.slot_one); + r3 = this->set_vlen(); + if (r1 == OK && r3 == OK) + this->write_vec_guard(s2, this->curr_instr->operands.vector.slot_two); + this->status = (r1 == OK && r3 == OK) ? OK : STALLED; + return; + case LOAD: + s2 = GET_LS_BITS(s1, s0b); + s1 = GET_MID_BITS(s1, s0b, s1b); break; default: s2 = GET_MID_BITS(s1, s0b, s1b); @@ -162,15 +238,18 @@ void ID::decode_I_type( } r1 = this->read_guard(s1); - if (r1 == OK) + this->curr_instr->operands.integer.slot_one = s1; + if (r1 == OK){ this->write_guard(s2); + this->curr_instr->operands.integer.slot_two = s2; + } this->status = r1; } -void ID::decode_J_type( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +void ID::decode_J_type(signed int &s1) { Response r1, r2; + signed int s2,s3; unsigned int s0b, s1b; s0b = REG_SIZE; @@ -179,15 +258,17 @@ void ID::decode_J_type( s2 = GET_BITS_SIGN_EXTEND(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); - switch (m) { + switch (this->curr_instr->mnemonic) { case PUSH: s2 = s1; // source s3 = 2; // stack pointer s1 = -1; // increment amount r1 = this->read_guard(s2); + this->curr_instr->operands.integer.slot_two = 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->curr_instr->operands.integer.slot_three = s3; } this->status = (r1 == OK && r2 == OK) ? OK : STALLED; break; @@ -198,7 +279,9 @@ void ID::decode_J_type( r1 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer if (r1 == OK) { this->write_guard(s2); + this->curr_instr->operands.integer.slot_two = s2; this->write_guard(s3); // we write the stack pointer + this->curr_instr->operands.integer.slot_three = s3; } this->status = r1; break; @@ -207,6 +290,7 @@ void ID::decode_J_type( [[fallthrough]]; default: this->status = this->read_guard(s1); + this->curr_instr->operands.integer.slot_one = s1; } } diff --git a/src/stage.cc b/src/stage.cc index 55756b6..47e7e32 100644 --- a/src/stage.cc +++ b/src/stage.cc @@ -16,6 +16,7 @@ // along with this program. If not, see <https://www.gnu.org/licenses/>. #include "stage.h" +#include "pipe_spec.h" #include <array> #include <deque> @@ -29,7 +30,7 @@ Stage::Stage(Stage *next) Stage::~Stage() { delete this->next; }; std::array<int, GPR_NUM> Stage::gprs; -std::array<int, V_NUM> Stage::vrs; +std::array<std::array<signed int, V_R_LIMIT>, V_NUM> Stage::vrs; std::deque<signed int> Stage::checked_out; unsigned int Stage::pc; Storage *Stage::storage; @@ -65,6 +66,14 @@ InstrDTO *Stage::advance(Response p) return r; } +bool Stage::is_vector_type(Mnemonic m){ + return (m == ADDV || m == SUBV || m == MULV || m == DIVV || m == CEV || m == LOADV || m == STOREV); +} + +bool Stage::is_logical(Mnemonic m){ + return (m == ANDI || m == ORI || m == XORI || m == AND || m == OR || m == XOR || m== NOT); +} + std::vector<int> Stage::stage_info() { std::vector<int> info; @@ -86,32 +95,6 @@ void Stage::set_condition(CC c, bool v) this->gprs[3] = this->gprs[3] & ~(1 << c); } -signed int Stage::dereference_register(signed int v) -{ - signed int r; - - if (v < 0 || v >= GPR_NUM + V_NUM) { - throw std::out_of_range( - "instruction tried to access register which does not exist"); - } - - r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[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( - "instruction tried to access register which does not exist"); - } - - 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/vec.cc b/src/vec.cc deleted file mode 100644 index e3e0a6c..0000000 --- a/src/vec.cc +++ /dev/null @@ -1,113 +0,0 @@ -#include "vec.h" - -template<typename T> -Vec<T> Vec<T>::operator+(const Vec<T>& other) const { - if (data.size() != other.data.size()) throw std::invalid_argument("Size mismatch"); - Vec<T> result; - for (size_t i = 0; i < data.size(); ++i) - result.data.push_back(data[i] + other.data[i]); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator-(const Vec<T>& other) const { - if (data.size() != other.data.size()) throw std::invalid_argument("Size mismatch"); - Vec<T> result; - for (size_t i = 0; i < data.size(); ++i) - result.data.push_back(data[i] - other.data[i]); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator*(const Vec<T>& other) const { - if (data.size() != other.data.size()) throw std::invalid_argument("Size mismatch"); - Vec<T> result; - for (size_t i = 0; i < data.size(); ++i) - result.data.push_back(data[i] * other.data[i]); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator/(const Vec<T>& other) const { - if (data.size() != other.data.size()) throw std::invalid_argument("Size mismatch"); - Vec<T> result; - for (size_t i = 0; i < data.size(); ++i) - result.data.push_back(other.data[i] == 0 ? 0 : data[i] / other.data[i]); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator%(const Vec<T>& other) const { - if (data.size() != other.data.size()) throw std::invalid_argument("Size mismatch"); - Vec<T> result; - for (size_t i = 0; i < data.size(); ++i) - result.data.push_back(other.data[i] == 0 ? 0 : data[i] % other.data[i]); - return result; -} - -// Scalar versions -template<typename T> -Vec<T> Vec<T>::operator+(T scalar) const { - Vec<T> result; - for (const auto& val : data) result.data.push_back(val + scalar); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator-(T scalar) const { - Vec<T> result; - for (const auto& val : data) result.data.push_back(val - scalar); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator*(T scalar) const { - Vec<T> result; - for (const auto& val : data) result.data.push_back(val * scalar); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator/(T scalar) const { - Vec<T> result; - for (const auto& val : data) result.data.push_back(scalar == 0 ? 0 : val / scalar); - return result; -} - -template<typename T> -Vec<T> Vec<T>::operator%(T scalar) const { - Vec<T> result; - for (const auto& val : data) result.data.push_back(scalar == 0 ? 0 : val % scalar); - return result; -} - -// Scalar - Vector versions -template<typename T> -Vec<T> operator-(T scalar, const Vec<T>& vec) { - Vec<T> result; - for (size_t i = 0; i < vec.size(); ++i) - result = result + (scalar - vec.data[i]); - return result; -} - -template<typename T> -Vec<T> operator/(T scalar, const Vec<T>& vec) { - Vec<T> result; - for (auto val : vec.data) - result = result + (val == 0 ? 0 : scalar / val); - return result; -} - -template<typename T> -Vec<T> operator%(T scalar, const Vec<T>& vec) { - Vec<T> result; - for (auto val : vec.data) - result = result + (val == 0 ? 0 : scalar % val); - return result; -} - -template<typename T> -void Vec<T>::print() const { - for (auto val : data) std::cout << val << " "; - std::cout << std::endl; -} @@ -45,13 +45,13 @@ void WB::write_handler() // POP performs a second register write reg = this->checked_out.front(); this->checked_out.pop_front(); - this->store_register( + this->store_register<signed int>( reg, this->curr_instr->operands.integer.slot_three); } this->checked_out.pop_front(); reg = this->curr_instr->checked_out; - this->store_register(reg, this->curr_instr->operands.integer.slot_one); + this->store_register<signed int>(reg, this->curr_instr->operands.integer.slot_one); } void WB::jump_handler() |