diff options
Diffstat (limited to 'src/id.cc')
-rw-r--r-- | src/id.cc | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/src/id.cc b/src/id.cc new file mode 100644 index 0000000..d2a8f02 --- /dev/null +++ b/src/id.cc @@ -0,0 +1,213 @@ +// Simulator for the RISC-V[ECTOR] mini-ISA +// Copyright (C) 2025 Siddarth Suresh +// Copyright (C) 2025 bdunahu + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +#include "id.h" +#include "instr.h" +#include "instrDTO.h" +#include "logger.h" +#include "response.h" +#include "stage.h" + +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::read_guard(signed int &v) +{ + Response r; + if (this->is_checked_out(v)) + r = STALLED; + else { + r = OK; + v = this->dereference_register(v); + } + return r; +} + +void ID::write_guard(signed int &v) +{ + // 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; + } + v = this->dereference_register(v); +} + +void ID::advance_helper() +{ + signed int s1, s2, s3; + Mnemonic m; + + if (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; + } + } +} + +void ID::get_instr_fields( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +{ + unsigned int type; + this->split_instr(s1, type, m); + + switch (type) { + case 0b00: + this->decode_R_type(s1, s2, s3, m); + break; + case 0b01: + this->decode_I_type(s1, s2, s3, m); + break; + case 0b10: + this->decode_J_type(s1, s2, s3, m); + break; + case 0b11: + m = NOP; + this->status = OK; + } +} + +void ID::decode_R_type( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +{ + unsigned int s0b, s1b, s2b; + Response r1, r2; + + s0b = REG_SIZE; + s1b = s0b + REG_SIZE; + s2b = s1b + REG_SIZE; + s3 = GET_MID_BITS(s1, s1b, s2b); + 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; + + switch (m) { + case CMP: + case CEV: + break; + default: + if (this->status == OK) + this->write_guard(s3); + } +} + +void ID::decode_I_type( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +{ + unsigned int s0b, s1b, s2b; + Response r1, r2; + + s0b = REG_SIZE; + s1b = s0b + REG_SIZE; + s2b = WORD_SPEC - LINE_SPEC - OPCODE_SIZE; + s3 = GET_BITS_SIGN_EXTEND(s1, s1b, s2b); + + switch (m) { + 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); + r2 = this->read_guard(s2); + this->status = (r1 == OK && r2 == OK) ? OK : STALLED; + return; + case LOAD: + case LOADV: + s2 = GET_LS_BITS(s1, s0b); + s1 = GET_MID_BITS(s1, s0b, s1b); + break; + default: + s2 = GET_MID_BITS(s1, s0b, s1b); + s1 = GET_LS_BITS(s1, s0b); + } + + r1 = this->read_guard(s1); + if (r1 == OK) + this->write_guard(s2); + this->status = r1; +} + +void ID::decode_J_type( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) +{ + Response r1, r2; + unsigned int s0b, s1b; + + s0b = REG_SIZE; + s1b = WORD_SPEC - LINE_SPEC - OPCODE_SIZE; + s3 = 0; + s2 = GET_BITS_SIGN_EXTEND(s1, s0b, s1b); + s1 = GET_LS_BITS(s1, s0b); + + switch (m) { + case PUSH: + s2 = s1; // source + 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 + if (r1 == OK && r2 == OK) { + this->write_guard(s3); // we write the stack pointer + } + 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 + if (r1 == OK) { + this->write_guard(s2); + this->write_guard(s3); // we write the stack pointer + } + this->status = r1; + break; + case RET: + s1 = 1; // link register + [[fallthrough]]; + default: + this->status = this->read_guard(s1); + } + +} |