summaryrefslogtreecommitdiff
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
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)
-rw-r--r--gui/gui.h22
-rw-r--r--inc/ex.h10
-rw-r--r--inc/instr.h7
-rw-r--r--inc/instrDTO.h4
-rw-r--r--inc/mm.h13
-rw-r--r--inc/wb.h3
-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
-rw-r--r--tests/ex.cc4
-rw-r--r--tests/id.cc4
13 files changed, 181 insertions, 115 deletions
diff --git a/gui/gui.h b/gui/gui.h
index 3f82898..a1d97ad 100644
--- a/gui/gui.h
+++ b/gui/gui.h
@@ -160,17 +160,17 @@ class GUI : public QMainWindow
{Mnemonic::SUBV, "SUBV"}, {Mnemonic::MULV, "MULV"},
{Mnemonic::DIVV, "DIVV"}, {Mnemonic::CMP, "CMP"},
{Mnemonic::CEV, "CEV"}, {Mnemonic::LOAD, "LOAD"},
- {Mnemonic::LOADV, "LOADV"}, {Mnemonic::ADDI, "ADDI"},
- {Mnemonic::SUBI, "SUBI"}, {Mnemonic::SFTRI, "SFTRI"},
- {Mnemonic::SFTLI, "SFTLI"}, {Mnemonic::ANDI, "ANDI"},
- {Mnemonic::ORI, "ORI"}, {Mnemonic::XORI, "XORI"},
- {Mnemonic::STORE, "STORE"}, {Mnemonic::STOREV, "STOREV"},
- {Mnemonic::JMP, "JMP"}, {Mnemonic::JRL, "JRL"},
- {Mnemonic::JAL, "JAL"}, {Mnemonic::BEQ, "BEQ"},
- {Mnemonic::BGT, "BGT"}, {Mnemonic::BUF, "BUF"},
- {Mnemonic::BOF, "BOF"}, {Mnemonic::PUSH, "PUSH"},
- {Mnemonic::POP, "POP"}, {Mnemonic::NOP, "NOP"},
- {Mnemonic::RET, "RET"},
+ {Mnemonic::ADDI, "ADDI"}, {Mnemonic::SUBI, "SUBI"},
+ {Mnemonic::SFTRI, "SFTRI"}, {Mnemonic::SFTLI, "SFTLI"},
+ {Mnemonic::ANDI, "ANDI"}, {Mnemonic::ORI, "ORI"},
+ {Mnemonic::XORI, "XORI"}, {Mnemonic::STORE, "STORE"},
+ {Mnemonic::SRDL, "SRDL"}, {Mnemonic::SRDS, "SRDS"},
+ {Mnemonic::ROTV, "ROTV"}, {Mnemonic::JMP, "JMP"},
+ {Mnemonic::JRL, "JRL"}, {Mnemonic::JAL, "JAL"},
+ {Mnemonic::BEQ, "BEQ"}, {Mnemonic::BGT, "BGT"},
+ {Mnemonic::BUF, "BUF"}, {Mnemonic::BOF, "BOF"},
+ {Mnemonic::PUSH, "PUSH"}, {Mnemonic::POP, "POP"},
+ {Mnemonic::NOP, "NOP"}, {Mnemonic::RET, "RET"},
};
QString mnemonicToString(Mnemonic mnemonic)
{
diff --git a/inc/ex.h b/inc/ex.h
index ff4041b..64eecb7 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -78,7 +78,6 @@ class EX : public Stage
* 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
*/
@@ -89,14 +88,17 @@ class EX : public Stage
unsigned int v_len);
/**
- * Handles operations involving a single vector register.
- * Currently, this is LOADV and STOREV
+ * Handles operations involving a vector result and a scalar.
* @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);
+ void handle_s_vector_operations(
+ std::array<signed int, V_R_LIMIT> &s1,
+ signed int s2,
+ Mnemonic m,
+ unsigned int v_len);
/**
* Wrapper for division functions, which detects HALT instructinos (division
* by 0).
diff --git a/inc/instr.h b/inc/instr.h
index 0c49a79..5a8ff4a 100644
--- a/inc/instr.h
+++ b/inc/instr.h
@@ -37,8 +37,10 @@ enum Mnemonic {
DIVV,
CMP,
CEV,
+ SRDL,
+ SRDS,
+ ROTV,
LOAD,
- LOADV,
ADDI,
SUBI,
SFTRI,
@@ -47,7 +49,6 @@ enum Mnemonic {
ORI,
XORI,
STORE,
- STOREV,
JMP,
JRL,
JAL,
@@ -64,7 +65,7 @@ enum Mnemonic {
enum FieldType {
SI_INT,
R_VECT,
- I_VECT,
+ S_VECT,
};
namespace instr
diff --git a/inc/instrDTO.h b/inc/instrDTO.h
index ccc6ed9..5d6a4eb 100644
--- a/inc/instrDTO.h
+++ b/inc/instrDTO.h
@@ -35,7 +35,7 @@ struct V_TYPE {
};
struct VI_TYPE {
- signed int slot_one;
+ std::array<signed int, V_R_LIMIT> slot_one;
signed int slot_two;
std::array<signed int, V_R_LIMIT> slot_three;
};
@@ -68,7 +68,7 @@ struct InstrDTO {
union {
struct U_INT_TYPE integer;
struct V_TYPE vector;
- struct VI_TYPE i_vector;
+ struct VI_TYPE s_vector;
} operands;
};
diff --git a/inc/mm.h b/inc/mm.h
index 230b258..d54d6ad 100644
--- a/inc/mm.h
+++ b/inc/mm.h
@@ -29,6 +29,19 @@ class MM : public Stage
private:
void advance_helper() override;
+ /**
+ * Helpers for `advance_helper'. Sets the `this->status' to OK
+ * If the current memory IO returned OK, and all vector elements
+ * have been processed. Otherwise, sets `this->status' to STALLED
+ * @param the response from the storage devices.
+ */
+ void try_start();
+ void try_finish(int response);
+ /**
+ * The index element currently being loaded or stored.
+ * Used for strided load/store.
+ */
+ int curr_element = 0;
};
#endif /* MM_H_INCLUDED */
diff --git a/inc/wb.h b/inc/wb.h
index 35c9240..bbba5bf 100644
--- a/inc/wb.h
+++ b/inc/wb.h
@@ -51,7 +51,8 @@ class WB : public Stage
* @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.
+ * of elements. Correctly handles zeroing out ALU operations if the VECTOR
+ * LENGTH number is zero.
*/
std::array<signed int, V_R_LIMIT> copy_extra_vector_elements();
};
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];
diff --git a/tests/ex.cc b/tests/ex.cc
index 5972182..5dbbe32 100644
--- a/tests/ex.cc
+++ b/tests/ex.cc
@@ -538,7 +538,7 @@ TEST_CASE_METHOD(EXFixture, "LOAD", "[ex]")
delete i;
}
-// TEST_CASE_METHOD(EXFixture, "LOADV", "[ex]")
+// TEST_CASE_METHOD(EXFixture, "SRDL", "[ex]")
// {
// }
@@ -763,7 +763,7 @@ TEST_CASE_METHOD(EXFixture, "STORE", "[ex]")
delete i;
}
-// TEST_CASE_METHOD(EXFixture, "STOREV", "[ex]")
+// TEST_CASE_METHOD(EXFixture, "SRDS", "[ex]")
// {
// }
diff --git a/tests/id.cc b/tests/id.cc
index b52ad9c..20b3200 100644
--- a/tests/id.cc
+++ b/tests/id.cc
@@ -166,13 +166,13 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]")
signed int t;
InstrDTO *i;
- t = this->encode_I_type(0xCC, 0b10101, 0b00110, 0b11011, 0b1);
+ t = this->encode_I_type(0xCC, 0b10101, 0b00110, 0b11010, 0b1);
i = this->decode_bits(t);
CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty
CHECK(i->operands.integer.slot_two == 0x00000000);
CHECK(i->operands.integer.slot_three == 0xCC);
- CHECK(i->mnemonic == STOREV);
+ CHECK(i->mnemonic == STORE);
delete i;
}