diff options
author | Siddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com> | 2025-05-11 23:39:06 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-11 23:39:06 -0400 |
commit | f02bea04284d33a2d014f636baa6a861b73f6c41 (patch) | |
tree | ce89a55af60b01f6b4129d7539d07c08bfaa1b9a /src | |
parent | a35eb451889f0efa99ff7fe1c0a3a76afd5e7ad5 (diff) | |
parent | 43588597069587f6846a7d64a1957435bec5429d (diff) |
Replace LOADV, STOREV, with strided load (SRDL), strided store (SRDS), add vector rotate (ROTV)
Diffstat (limited to 'src')
-rw-r--r-- | src/ex.cc | 41 | ||||
-rw-r--r-- | src/id.cc | 81 | ||||
-rw-r--r-- | src/instr.cc | 30 | ||||
-rw-r--r-- | src/mm.cc | 64 | ||||
-rw-r--r-- | src/wb.cc | 13 |
5 files changed, 139 insertions, 90 deletions
@@ -240,21 +240,36 @@ void EX::handle_vector_operations( this->set_condition(UF, underflow); } -void EX::handle_i_vector_operations(signed int &s1, signed int s2, Mnemonic m) +void EX::handle_s_vector_operations( + std::array<signed int, V_R_LIMIT> &s1, + signed int s2, + Mnemonic m, + unsigned int v_len) { - switch (m) { - case LOADV: - case STOREV: - s1 = s1 + s2; - break; + unsigned int i, inc1, inc2; - case RET: - case NOP: + switch (m) { + case ROTV: + s2 = s2 % v_len; + if (s2 < 0) + s2 += v_len; + + std::rotate(s1.begin(), s1.begin() + s2, s1.begin() + v_len); + break; + case SRDL: + case SRDS: + inc1 = s1[0]; + s1[0] = s2; + for (i = 1; i < v_len; ++i) { + inc2 = s1[i]; + s1[i] = s1[i - 1] + inc1; + inc1 = inc2; + } break; default: - throw std::invalid_argument("handle_i_vector_operations did not " - "receive a LOADV or STOREV operation!"); + throw std::invalid_argument("handle_s_vector_operations did not " + "receive a SRDL or SRDS operation!"); } } @@ -275,9 +290,9 @@ void EX::advance_helper() this->curr_instr->operands.vector.slot_one, this->curr_instr->operands.vector.slot_two, m, v_len_or_pc); } else { - handle_i_vector_operations( - this->curr_instr->operands.i_vector.slot_one, - this->curr_instr->operands.i_vector.slot_two, m); + handle_s_vector_operations( + this->curr_instr->operands.s_vector.slot_one, + this->curr_instr->operands.s_vector.slot_two, m, v_len_or_pc); } this->status = OK; @@ -99,37 +99,58 @@ void ID::decode_R_type(signed int &s1) s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); - if (this->curr_instr->type == SI_INT) { + switch (this->curr_instr->type) { + case SI_INT: r1 = this->read_guard<signed int>( s1, this->curr_instr->operands.integer.slot_one); r2 = this->read_guard<signed int>( s2, this->curr_instr->operands.integer.slot_two); r3 = OK; - } else { + break; + case R_VECT: r1 = this->read_guard<std::array<signed int, V_R_LIMIT>>( s1, this->curr_instr->operands.vector.slot_one); r2 = this->read_guard<std::array<signed int, V_R_LIMIT>>( s2, this->curr_instr->operands.vector.slot_two); r3 = this->set_vlen(); + break; + case S_VECT: + // store the second field in s1, to keep execute+mem consistent + r1 = this->read_guard<std::array<signed int, V_R_LIMIT>>( + s2, this->curr_instr->operands.s_vector.slot_one); + r2 = this->read_guard<signed int>( + s1, this->curr_instr->operands.s_vector.slot_two); + r3 = this->set_vlen(); + break; } 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) { + if (this->status == OK) { + switch (this->curr_instr->mnemonic) { + case CMP: + case CEV: + break; + case ADDV: + case SUBV: + case MULV: + case DIVV: this->curr_instr->operands.vector.slot_three = this->write_guard<std::array<signed int, V_R_LIMIT>>(s3); - } - break; - default: - if (this->status == OK) { + break; + case ROTV: + case SRDL: + this->curr_instr->operands.s_vector.slot_three = + this->write_guard<std::array<signed int, V_R_LIMIT>>(s3); + break; + case SRDS: + r1 = this->read_guard<std::array<signed int, V_R_LIMIT>>( + s3, this->curr_instr->operands.s_vector.slot_three); + if (r1 != OK) { + this->status = STALLED; + } + break; + default: this->curr_instr->operands.integer.slot_three = this->write_guard<signed int>(s3); } @@ -141,7 +162,6 @@ 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; @@ -164,35 +184,6 @@ void ID::decode_I_type(signed int &s1) this->curr_instr->operands.integer.slot_two = s2; this->status = (r1 == OK && r2 == OK) ? OK : STALLED; return; - case STOREV: - this->curr_instr->operands.i_vector.slot_two = s3; - s2 = GET_MID_BITS(s1, s0b, s1b); - s1 = GET_LS_BITS(s1, s0b); - - // base address - r1 = this->read_guard<signed int>(s1, s1); - this->curr_instr->operands.i_vector.slot_one = s1; - // vector value to be stored - r2 = this->read_guard<std::array<signed int, V_R_LIMIT>>( - s2, this->curr_instr->operands.i_vector.slot_three); - r3 = this->set_vlen(); - - this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED; - return; - case LOADV: - this->curr_instr->operands.i_vector.slot_two = s3; - s2 = GET_LS_BITS(s1, s0b); - s1 = GET_MID_BITS(s1, s0b, s1b); - // base address - r1 = this->read_guard<signed int>(s1, s1); - this->curr_instr->operands.i_vector.slot_one = s1; - r3 = this->set_vlen(); - if (r1 == OK && r3 == OK) - // vector destination - this->curr_instr->operands.i_vector.slot_three = - this->write_guard<std::array<signed int, V_R_LIMIT>>(s2); - this->status = (r1 == OK && r3 == OK) ? OK : STALLED; - return; case LOAD: this->curr_instr->operands.integer.slot_three = s3; s2 = GET_LS_BITS(s1, s0b); diff --git a/src/instr.cc b/src/instr.cc index ee2d37f..a638a38 100644 --- a/src/instr.cc +++ b/src/instr.cc @@ -23,27 +23,27 @@ namespace instr { const std::unordered_map<unsigned int, Mnemonic> mnemonic_map = { - {0b0000100, ADD}, {0b0001000, SUB}, {0b0001100, MUL}, - {0b0010000, QUOT}, {0b0010100, REM}, {0b0011000, SFTR}, - {0b0011100, SFTL}, {0b0100000, AND}, {0b0100100, OR}, - {0b0101000, NOT}, {0b0101100, XOR}, {0b0110000, ADDV}, - {0b0110100, SUBV}, {0b0111000, MULV}, {0b0111100, DIVV}, - {0b1000000, CMP}, {0b1000100, CEV}, {0b000101, LOAD}, - {0b001001, LOADV}, {0b0001101, ADDI}, {0b0010001, SUBI}, - {0b0010101, SFTRI}, {0b0011001, SFTLI}, {0b0011101, ANDI}, - {0b0100001, ORI}, {0b0100101, XORI}, {0b0101001, STORE}, - {0b0101101, STOREV}, {0b0000110, JMP}, {0b0001010, JRL}, - {0b0001110, JAL}, {0b0010010, BEQ}, {0b0010110, BGT}, - {0b0011010, BUF}, {0b0011110, BOF}, {0b0100010, PUSH}, - {0b0100110, POP}, {0b0101010, RET}, + {0b0000100, ADD}, {0b0001000, SUB}, {0b0001100, MUL}, + {0b0010000, QUOT}, {0b0010100, REM}, {0b0011000, SFTR}, + {0b0011100, SFTL}, {0b0100000, AND}, {0b0100100, OR}, + {0b0101000, NOT}, {0b0101100, XOR}, {0b0110000, ADDV}, + {0b0110100, SUBV}, {0b0111000, MULV}, {0b0111100, DIVV}, + {0b1000000, CMP}, {0b1000100, CEV}, {0b1001000, SRDL}, + {0b1001100, SRDS}, {0b1010000, ROTV}, {0b000101, LOAD}, + {0b0001001, ADDI}, {0b0001101, SUBI}, {0b0010001, SFTRI}, + {0b0010101, SFTLI}, {0b0011001, ANDI}, {0b0011101, ORI}, + {0b0100001, XORI}, {0b0100101, STORE}, {0b0000110, JMP}, + {0b0001010, JRL}, {0b0001110, JAL}, {0b0010010, BEQ}, + {0b0010110, BGT}, {0b0011010, BUF}, {0b0011110, BOF}, + {0b0100010, PUSH}, {0b0100110, POP}, {0b0101010, RET}, }; FieldType get_field_types(Mnemonic m) { if (m == ADDV || m == SUBV || m == MULV || m == DIVV || m == CEV) { return R_VECT; - } else if (m == STOREV || m == LOADV) { - return I_VECT; + } else if (m == SRDL || m == SRDS || m == ROTV) { + return S_VECT; } else { return SI_INT; } @@ -25,15 +25,30 @@ void MM::advance_helper() signed int data; int i; + this->try_start(); + if (this->status == OK) { + return; + } + switch (this->curr_instr->mnemonic) { case LOAD: i = this->storage->read_word( this, this->curr_instr->operands.integer.slot_one, data); - this->status = i ? OK : STALLED; - if (this->status == OK) { + if (i) { this->curr_instr->operands.integer.slot_one = data; - } else - this->status = STALLED; + } + this->try_finish(i); + break; + case SRDL: + i = this->storage->read_word( + this, + this->curr_instr->operands.s_vector.slot_one[this->curr_element], + data); + if (i) { + this->curr_instr->operands.s_vector.slot_one[this->curr_element] = + data; + } + this->try_finish(i); break; case PUSH: @@ -41,22 +56,47 @@ void MM::advance_helper() i = this->storage->write_word( this, this->curr_instr->operands.integer.slot_two, this->curr_instr->operands.integer.slot_one); - this->status = i ? OK : STALLED; - if (this->status != OK) { - this->status = STALLED; - } + this->try_finish(i); + break; + case SRDS: + i = this->storage->write_word( + this, + this->curr_instr->operands.s_vector.slot_three[this->curr_element], + this->curr_instr->operands.s_vector.slot_one[this->curr_element]); + this->try_finish(i); break; case POP: - i = this->storage->read_word(this, this->curr_instr->operands.integer.slot_three, data); + i = this->storage->read_word( + this, this->curr_instr->operands.integer.slot_three, data); this->status = i ? OK : STALLED; - if (this->status == OK) { + if (i) { this->curr_instr->operands.integer.slot_three = data; - } else - this->status = STALLED; + } break; default: this->status = OK; } } + +void MM::try_start() +{ + if (this->curr_instr->type != SI_INT) { + this->status = + (this->curr_element >= this->curr_instr->slot_B) ? OK : STALLED; + } + if (this->status == OK) + this->curr_element = 0; +} + +void MM::try_finish(int response) +{ + if (this->curr_instr->type == SI_INT) { + this->status = response ? OK : STALLED; + } else { + if (response) { + ++this->curr_element; + } + } +} @@ -58,15 +58,11 @@ void WB::write_handler() this->store_register<signed int>( reg, this->curr_instr->operands.integer.slot_one); break; + case S_VECT: case R_VECT: this->store_register<std::array<signed int, V_R_LIMIT>>( reg, this->copy_extra_vector_elements()); break; - case I_VECT: - this->store_register<std::array<signed int, V_R_LIMIT>>( - reg, this->curr_instr->operands.i_vector.slot_three); - // todo, use copy_extra_vector_elements - break; } } @@ -97,6 +93,13 @@ std::array<signed int, V_R_LIMIT> WB::copy_extra_vector_elements() int i; std::array<signed int, V_R_LIMIT> v; + if (this->curr_instr->type == R_VECT) { + if (this->curr_instr->slot_B == 0) { + v = {0}; + return v; + } + } + v = this->curr_instr->operands.vector.slot_one; for (i = V_R_LIMIT - 1; i >= this->curr_instr->slot_B; --i) { v[i] = this->curr_instr->operands.vector.slot_three[i]; |