summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSiddarth Suresh <155843085+SiddarthSuresh98@users.noreply.github.com>2025-05-11 23:39:06 -0400
committerGitHub <noreply@github.com>2025-05-11 23:39:06 -0400
commitf02bea04284d33a2d014f636baa6a861b73f6c41 (patch)
treece89a55af60b01f6b4129d7539d07c08bfaa1b9a /src
parenta35eb451889f0efa99ff7fe1c0a3a76afd5e7ad5 (diff)
parent43588597069587f6846a7d64a1957435bec5429d (diff)
Merge pull request #79 from bdunahu/bdunahuHEADmaster
Replace LOADV, STOREV, with strided load (SRDL), strided store (SRDS), add vector rotate (ROTV)
Diffstat (limited to 'src')
-rw-r--r--src/ex.cc41
-rw-r--r--src/id.cc81
-rw-r--r--src/instr.cc30
-rw-r--r--src/mm.cc64
-rw-r--r--src/wb.cc13
5 files changed, 139 insertions, 90 deletions
diff --git a/src/ex.cc b/src/ex.cc
index 56a59d7..f36ea4b 100644
--- a/src/ex.cc
+++ b/src/ex.cc
@@ -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;
diff --git a/src/id.cc b/src/id.cc
index 85637a6..58bde6b 100644
--- a/src/id.cc
+++ b/src/id.cc
@@ -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;
}
diff --git a/src/mm.cc b/src/mm.cc
index ac77433..63ee16a 100644
--- a/src/mm.cc
+++ b/src/mm.cc
@@ -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;
+ }
+ }
+}
diff --git a/src/wb.cc b/src/wb.cc
index bfdbc3a..7320f4f 100644
--- a/src/wb.cc
+++ b/src/wb.cc
@@ -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];