summaryrefslogtreecommitdiff
path: root/src/id.cc
diff options
context:
space:
mode:
authorbd <bdunaisky@umass.edu>2025-04-28 03:44:42 +0000
committerGitHub <noreply@github.com>2025-04-28 03:44:42 +0000
commit013a79547aa465872d0262b2f5c24e73f9556869 (patch)
tree28cc8f2ea6e5aa1a74f328de8594b0ad5995fa66 /src/id.cc
parent5653b2a033e7a4173d2f178b5ce52384666d3d7b (diff)
parent336faf3fd701aaf962613abd1ff0a69cbdf021ce (diff)
Merge pull request #69 from bdunahu/vector_ext
Vector ext
Diffstat (limited to 'src/id.cc')
-rw-r--r--src/id.cc221
1 files changed, 166 insertions, 55 deletions
diff --git a/src/id.cc b/src/id.cc
index d2a8f02..e4790ef 100644
--- a/src/id.cc
+++ b/src/id.cc
@@ -22,30 +22,27 @@
#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,55 +56,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:
- m = NOP;
+ // 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;
@@ -116,62 +153,124 @@ 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)
+ 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 is immediate
s3 = GET_BITS_SIGN_EXTEND(s1, s1b, s2b);
- switch (m) {
+ switch (this->curr_instr->mnemonic) {
case STORE:
- case STOREV:
+ this->curr_instr->operands.integer.slot_three = s3;
s2 = GET_MID_BITS(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
// both operands are read values
+ // s1 is base address
r1 = this->read_guard(s1);
+ this->curr_instr->operands.integer.slot_one = s1;
+ // s2 is value to be stored
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:
+ this->curr_instr->operands.load_store_vector.immediate = s3;
+ s2 = GET_MID_BITS(s1, s0b, s1b);
+ s1 = GET_LS_BITS(s1, s0b);
+
+ // base address
+ r1 = this->read_guard(s1);
+ this->curr_instr->operands.load_store_vector.base_addr = s1;
+ // vector value to be stored
+ r2 = this->read_vec_guard(
+ s2, this->curr_instr->operands.load_store_vector.vector_register);
+ r3 = this->set_vlen();
+
+ this->status = (r1 == OK && r2 == OK && r3 == OK) ? OK : STALLED;
+ return;
case LOADV:
+ this->curr_instr->operands.load_store_vector.immediate = s3;
+ s2 = GET_LS_BITS(s1, s0b);
+ s1 = GET_MID_BITS(s1, s0b, s1b);
+ // base address
+ r1 = this->read_guard(s1);
+ this->curr_instr->operands.load_store_vector.base_addr = s1;
+ r3 = this->set_vlen();
+ if (r1 == OK && r3 == OK)
+ // vector destination
+ this->write_vec_guard(
+ s2,
+ this->curr_instr->operands.load_store_vector.vector_register);
+ 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);
s1 = GET_MID_BITS(s1, s0b, s1b);
break;
default:
+ this->curr_instr->operands.integer.slot_three = s3;
s2 = GET_MID_BITS(s1, s0b, s1b);
s1 = GET_LS_BITS(s1, s0b);
}
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;
@@ -180,26 +279,34 @@ 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
+ s3 = 2; // stack pointer
s1 = -1; // increment amount
r1 = this->read_guard(s2);
- r2 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ this->curr_instr->operands.integer.slot_one = s1;
+ 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;
case POP:
s2 = s1; // destination
- s3 = 2; // stack pointer
- s1 = 1; // increment amount
- r1 = (this->is_checked_out(s3)) ? STALLED : OK; // we read the stack pointer
+ s3 = 2; // stack pointer
+ s1 = 1; // increment amount
+ this->curr_instr->operands.integer.slot_one = s1;
+ 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;
@@ -208,6 +315,10 @@ void ID::decode_J_type(
[[fallthrough]];
default:
this->status = this->read_guard(s1);
+ if(this->status == OK){
+ this->curr_instr->operands.integer.slot_one = s1;
+ this->curr_instr->operands.integer.slot_two = s2;
+ this->curr_instr->operands.integer.slot_three = s3;
+ }
}
-
}