From baacedcc858d8d4857282cc7fb1881a11048a5bc Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 20:55:05 -0400 Subject: Remove subfolders --- src/controller.cc | 69 ++++++++ src/dum.cc | 38 +++++ src/ex.cc | 452 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/id.cc | 228 +++++++++++++++++++++++++ src/if.cc | 65 ++++++++ src/instr.cc | 40 +++++ src/instrDTO.cc | 70 ++++++++ src/logger.cc | 88 ++++++++++ src/logger/logger.cc | 88 ---------- src/mm.cc | 60 +++++++ src/response.cc | 25 +++ src/sim/controller.cc | 69 -------- src/sim/dum.cc | 38 ----- src/sim/ex.cc | 452 -------------------------------------------------- src/sim/id.cc | 230 ------------------------- src/sim/if.cc | 65 -------- src/sim/instr.cc | 40 ----- src/sim/instrDTO.cc | 70 -------- src/sim/mm.cc | 60 ------- src/sim/stage.cc | 130 --------------- src/sim/wb.cc | 75 --------- src/stage.cc | 130 +++++++++++++++ src/utils/response.cc | 25 --- src/wb.cc | 75 +++++++++ 24 files changed, 1340 insertions(+), 1342 deletions(-) create mode 100644 src/controller.cc create mode 100644 src/dum.cc create mode 100644 src/ex.cc create mode 100644 src/id.cc create mode 100644 src/if.cc create mode 100644 src/instr.cc create mode 100644 src/instrDTO.cc create mode 100644 src/logger.cc delete mode 100644 src/logger/logger.cc create mode 100644 src/mm.cc create mode 100644 src/response.cc delete mode 100644 src/sim/controller.cc delete mode 100644 src/sim/dum.cc delete mode 100644 src/sim/ex.cc delete mode 100644 src/sim/id.cc delete mode 100644 src/sim/if.cc delete mode 100644 src/sim/instr.cc delete mode 100644 src/sim/instrDTO.cc delete mode 100644 src/sim/mm.cc delete mode 100644 src/sim/stage.cc delete mode 100644 src/sim/wb.cc create mode 100644 src/stage.cc delete mode 100644 src/utils/response.cc create mode 100644 src/wb.cc (limited to 'src') diff --git a/src/controller.cc b/src/controller.cc new file mode 100644 index 0000000..1c379ec --- /dev/null +++ b/src/controller.cc @@ -0,0 +1,69 @@ +// 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 . + +#include "controller.h" +#include "ex.h" +#include "response.h" +#include "storage.h" + +Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined) + : Stage(stage) +{ + this->clock_cycle = 1; + this->storage = storage; + this->is_pipelined = is_pipelined; + this->is_empty = true; + this->pc = 0x0; + this->checked_out = {}; + this->gprs = {0}; + this->gprs.at(2) = MEM_WORDS; // set the stack pointer +} + +void Controller::run_for(int number) +{ + int i; + for (i = 0; i < number; ++i) { + try { + this->advance(WAIT); + } catch (HaltException &e) { + break; + } + } +} + +int Controller::get_clock_cycle() { return this->clock_cycle; } + +std::array Controller::get_gprs() { return this->gprs; } + +int Controller::get_pc() { return this->pc; } + +InstrDTO *Controller::advance(Response p) +{ + InstrDTO *r; + r = this->next->advance(p); + ++this->clock_cycle; + + if (r) + this->is_empty = true; + + return r; +} + +void Controller::advance_helper() +{ + // TODO: check halt condition and call UI to refresh +} diff --git a/src/dum.cc b/src/dum.cc new file mode 100644 index 0000000..fd3b7a6 --- /dev/null +++ b/src/dum.cc @@ -0,0 +1,38 @@ +// 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 . + +#include "dum.h" +#include "instrDTO.h" +#include "response.h" +#include "stage.h" + +InstrDTO *DUM::advance(Response p) +{ + InstrDTO *r = nullptr; + + if (this->curr_instr && p == WAIT) { + r = new InstrDTO(*this->curr_instr); + delete this->curr_instr; + curr_instr = nullptr; + } + + return r; +} + +void DUM::advance_helper() {} + +void DUM::set_curr_instr(InstrDTO *d) { this->curr_instr = d; } diff --git a/src/ex.cc b/src/ex.cc new file mode 100644 index 0000000..117002c --- /dev/null +++ b/src/ex.cc @@ -0,0 +1,452 @@ +// 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 . + +#include "ex.h" +#include "instrDTO.h" +#include "pipe_spec.h" +#include "response.h" +#include "stage.h" +#include + +// clang-format off +#define INIT_INSTRUCTION(mnemonic, body) \ + {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \ + body; \ + }} +// clang-format on + +EX::EX(Stage *stage) : Stage(stage) +{ + instr_map = { + + /* R type instructions */ + INIT_INSTRUCTION( + ADD, + { + this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); + s1 = s1 + s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + SUB, + { + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); + s1 = s1 - s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + MUL, + { + this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); + this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); + s1 = s1 * s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + QUOT, + { + this->handle_divide(s1, s2, false); + (void)pc; + (void)s3; + }), + + INIT_INSTRUCTION( + REM, + { + this->handle_divide(s1, s2, true); + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + SFTR, + { + s1 = s1 >> s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + SFTL, + { + s1 = s1 << s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + AND, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 & s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + OR, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 | s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + NOT, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = ~s1; + (void)pc; + (void)s3; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + XOR, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 ^ s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + ADDV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + INIT_INSTRUCTION( + SUBV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + INIT_INSTRUCTION( + MULV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + INIT_INSTRUCTION( + DIVV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + INIT_INSTRUCTION( + CMP, + { + (s1 > s2) ? this->set_condition(GT, true) + : this->set_condition(GT, false); + (s1 == s2) ? this->set_condition(EQ, true) + : this->set_condition(EQ, false); + (void)pc; + (void)s3; + }), + + INIT_INSTRUCTION( + CEV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + /* I type instructions */ + INIT_INSTRUCTION( + LOAD, + { + s1 = s1 + s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + LOADV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + INIT_INSTRUCTION( + ADDI, + { + this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); + this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); + s1 = s1 + s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + SUBI, + { + this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); + this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); + s1 = s1 - s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + SFTRI, + { + s1 = s1 >> s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + SFTLI, + { + s1 = s1 << s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + ANDI, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 & s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + ORI, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 | s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + XORI, + { + this->set_condition(OF, false); + this->set_condition(UF, false); + s1 = s1 ^ s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + STORE, + { + s1 = s1 + s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + STOREV, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + /* J type instructions */ + INIT_INSTRUCTION( + JMP, + { + s1 = s1 + s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + JRL, + { + s1 = pc + s2; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + JAL, + { + s1 = s1 + s2; + (void)pc; + (void)s3; + (void)this; + }), + + INIT_INSTRUCTION( + BEQ, + { + (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1; + (void)s3; + }), + + INIT_INSTRUCTION( + BGT, + { + (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1; + (void)s3; + }), + + INIT_INSTRUCTION( + BUF, + { + (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1; + (void)s3; + }), + + INIT_INSTRUCTION( + BOF, + { + (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1; + (void)s3; + }), + + INIT_INSTRUCTION( + PUSH, + { + s1 = s1 + s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + POP, + { + s1 = s1 + s3; + (void)pc; + (void)s2; + (void)this; + }), + + INIT_INSTRUCTION( + RET, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + + /* NOP */ + INIT_INSTRUCTION( + NOP, + { + (void)pc; + (void)s3; + (void)s2; + (void)s1; + (void)this; + }), + }; +} + +void EX::advance_helper() +{ + signed int s1, s2, s3; + unsigned int pc; + Mnemonic m; + + m = this->curr_instr->get_mnemonic(); + s1 = this->curr_instr->get_s1(); + s2 = this->curr_instr->get_s2(); + s3 = this->curr_instr->get_s3(); + pc = this->curr_instr->get_pc(); + + this->instr_map[m](s1, s2, s3, pc); + + this->curr_instr->set_s1(s1); + this->status = OK; +} + +void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) +{ + this->set_condition(OF, DIVISION_OF_GUARD(s1, s2)); + this->set_condition(UF, false); + if (s2 == 0) { + // handle everything here + this->curr_instr->set_s1(MAX_INT); + this->status = OK; + throw HaltException(); + } else if ((s1 == -(MAX_INT)-1) && s2 == -1) { + // undefined in C++ + s1 = -(MAX_INT)-1; + } else { + s1 = (is_mod) ? (s1 % s2) : (s1 / s2); + } +} diff --git a/src/id.cc b/src/id.cc new file mode 100644 index 0000000..97bd844 --- /dev/null +++ b/src/id.cc @@ -0,0 +1,228 @@ +// 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 . + +#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->set_checked_out(v); + } + v = this->dereference_register(v); +} + +void ID::advance_helper() +{ + signed int s1, s2, s3; + Mnemonic m; + Type t; + + if (curr_instr->get_mnemonic() == NOP) + this->status = OK; + else { + s1 = curr_instr->get_instr_bits(); + get_instr_fields(s1, s2, s3, m, t); + if (this->status == OK) { + curr_instr->set_s1(s1); + curr_instr->set_s2(s2); + curr_instr->set_s3(s3); + curr_instr->set_mnemonic(m); + curr_instr->set_type(t); + } + } +} + +void ID::get_instr_fields( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) +{ + unsigned int type; + this->split_instr(s1, type, m); + + switch (type) { + case 0b00: + t = R; + this->decode_R_type(s1, s2, s3, m); + break; + case 0b01: + t = I; + this->decode_I_type(s1, s2, s3, m); + break; + case 0b10: + t = J; + this->decode_J_type(s1, s2, s3, m); + break; + case 0b11: + t = INV; + 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); + } + +} + +std::vector ID::stage_info() +{ + std::vector info; + if (this->curr_instr) { + info.push_back(this->curr_instr->is_squashed()); + info.push_back(this->curr_instr->get_instr_bits()); + } + return info; +} diff --git a/src/if.cc b/src/if.cc new file mode 100644 index 0000000..054c77c --- /dev/null +++ b/src/if.cc @@ -0,0 +1,65 @@ +// 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 . + +#include "if.h" +#include "instrDTO.h" +#include "response.h" +#include "stage.h" + +InstrDTO *IF::advance(Response p) +{ + InstrDTO *r = nullptr; + + this->advance_helper(); + if (this->curr_instr != nullptr && p == WAIT) { + // don't increment PC if the PC was just set by wb + if (this->curr_instr->is_squashed() != 1) + ++this->pc; + r = new InstrDTO(*this->curr_instr); + delete curr_instr; + curr_instr = nullptr; + } + + return r; +} + +std::vector IF::stage_info() { + std::vector info; + if(this->curr_instr){ + info.push_back(this->curr_instr->is_squashed()); + info.push_back(this->curr_instr->get_instr_bits()); + } + return info; +} + +void IF::advance_helper() +{ + Response r; + int i; + signed int bits; + + if (this->curr_instr == nullptr && (this->is_pipelined || this->is_empty)) { + i = this->storage->read_word(this, this->pc, bits); + r = i ? OK : STALLED; + if (r == OK) { + this->curr_instr = new InstrDTO(); + this->curr_instr->set_instr_bits(bits); + this->curr_instr->set_pc(this->pc); + this->is_empty = false; + } + } +} diff --git a/src/instr.cc b/src/instr.cc new file mode 100644 index 0000000..9bd951b --- /dev/null +++ b/src/instr.cc @@ -0,0 +1,40 @@ +// 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 . + +#include "instr.h" +#include +#include +#include + +namespace instr +{ +const std::unordered_map 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}, +}; +} // namespace instr diff --git a/src/instrDTO.cc b/src/instrDTO.cc new file mode 100644 index 0000000..cb093bb --- /dev/null +++ b/src/instrDTO.cc @@ -0,0 +1,70 @@ +// 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 . + +#include "instrDTO.h" + +InstrDTO::InstrDTO() +{ + this->instr_bits = 0; + this->checked_out = -1; + this->s1 = 0; + this->s2 = 0; + this->s3 = 0; + this->mnemonic = ADD; + this->type = INV; + this->pc = 0; + this->squashed = 0; +} + +signed int InstrDTO::get_instr_bits() { return this->instr_bits; } + +signed int InstrDTO::get_checked_out() { return this->checked_out; } + +signed int InstrDTO::get_s1() { return this->s1; } + +signed int InstrDTO::get_s2() { return this->s2; } + +signed int InstrDTO::get_s3() { return this->s3; } + +Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } + +Type InstrDTO::get_type() { return this->type; } + +unsigned int InstrDTO::get_pc() { return this->pc; } + +int InstrDTO::is_squashed() { return this->squashed; } + +void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } + +void InstrDTO::set_checked_out(signed int checked_out) +{ + this->checked_out = checked_out; +} + +void InstrDTO::set_s1(signed int s) { this->s1 = s; } + +void InstrDTO::set_s2(signed int s) { this->s2 = s; } + +void InstrDTO::set_s3(signed int s) { this->s3 = s; } + +void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; } + +void InstrDTO::set_type(Type t) { this->type = t; } + +void InstrDTO::set_pc(unsigned int pc) { this->pc = pc; } + +void InstrDTO::squash() { this->squashed = 1; } diff --git a/src/logger.cc b/src/logger.cc new file mode 100644 index 0000000..a665dcd --- /dev/null +++ b/src/logger.cc @@ -0,0 +1,88 @@ +// 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 . + +#include "logger.h" +#include +#include +#include +#include +using namespace std; + +LogLevel Logger::level = INFO; +Logger *Logger::logger_instance; + +void Logger::setLevel(LogLevel level) { this->level = level; } + +void Logger::log(LogLevel level, const string &message) +{ + if (level_to_int(level) > level_to_int(this->level)) { + return; + } + + time_t now = time(0); + tm *timeinfo = localtime(&now); + char timestamp[20]; + strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo); + + ostringstream logEntry; + logEntry << "[" << timestamp << "] " << level_to_string(level) << ": " + << message << endl; + + cout << logEntry.str(); +} + +Logger *Logger::getInstance() +{ + if (logger_instance == nullptr) { + logger_instance = new Logger(); + } + return logger_instance; +} + +string Logger::level_to_string(LogLevel level) +{ + switch (level) { + case DEBUG: + return "DEBUG"; + case INFO: + return "INFO"; + case WARNING: + return "WARNING"; + case ERROR: + return "ERROR"; + case CRITICAL: + return "CRITICAL"; + default: + return "UNKNOWN"; + } +} + +int Logger::level_to_int(LogLevel level) +{ + switch (level) { + case DEBUG: + return 5; + case INFO: + return 4; + case WARNING: + return 3; + case ERROR: + return 2; + default: + return 1; + } +} diff --git a/src/logger/logger.cc b/src/logger/logger.cc deleted file mode 100644 index a665dcd..0000000 --- a/src/logger/logger.cc +++ /dev/null @@ -1,88 +0,0 @@ -// 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 . - -#include "logger.h" -#include -#include -#include -#include -using namespace std; - -LogLevel Logger::level = INFO; -Logger *Logger::logger_instance; - -void Logger::setLevel(LogLevel level) { this->level = level; } - -void Logger::log(LogLevel level, const string &message) -{ - if (level_to_int(level) > level_to_int(this->level)) { - return; - } - - time_t now = time(0); - tm *timeinfo = localtime(&now); - char timestamp[20]; - strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M:%S", timeinfo); - - ostringstream logEntry; - logEntry << "[" << timestamp << "] " << level_to_string(level) << ": " - << message << endl; - - cout << logEntry.str(); -} - -Logger *Logger::getInstance() -{ - if (logger_instance == nullptr) { - logger_instance = new Logger(); - } - return logger_instance; -} - -string Logger::level_to_string(LogLevel level) -{ - switch (level) { - case DEBUG: - return "DEBUG"; - case INFO: - return "INFO"; - case WARNING: - return "WARNING"; - case ERROR: - return "ERROR"; - case CRITICAL: - return "CRITICAL"; - default: - return "UNKNOWN"; - } -} - -int Logger::level_to_int(LogLevel level) -{ - switch (level) { - case DEBUG: - return 5; - case INFO: - return 4; - case WARNING: - return 3; - case ERROR: - return 2; - default: - return 1; - } -} diff --git a/src/mm.cc b/src/mm.cc new file mode 100644 index 0000000..3df1578 --- /dev/null +++ b/src/mm.cc @@ -0,0 +1,60 @@ +// 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 . + +#include "mm.h" +#include "instrDTO.h" +#include "response.h" +#include "stage.h" + +void MM::advance_helper() +{ + signed int data; + int i; + + switch (this->curr_instr->get_mnemonic()) { + case LOAD: + i = this->storage->read_word(this, this->curr_instr->get_s1(), data); + this->status = i ? OK : STALLED; + if (this->status == OK) { + this->curr_instr->set_s1(data); + } else + this->status = STALLED; + break; + + case PUSH: + case STORE: + i = this->storage->write_word( + this, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + this->status = i ? OK : STALLED; + if (this->status != OK) { + this->status = STALLED; + } + break; + + case POP: + i = this->storage->read_word(this, this->curr_instr->get_s3(), data); + this->status = i ? OK : STALLED; + if (this->status == OK) { + this->curr_instr->set_s3(data); + } else + this->status = STALLED; + break; + + default: + this->status = OK; + } +} diff --git a/src/response.cc b/src/response.cc new file mode 100644 index 0000000..d56419a --- /dev/null +++ b/src/response.cc @@ -0,0 +1,25 @@ +// 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 . + +#include "response.h" +#include + +std::ostream &operator<<(std::ostream &os, Response r) +{ + const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; + return os << nameR[r]; +} diff --git a/src/sim/controller.cc b/src/sim/controller.cc deleted file mode 100644 index 1c379ec..0000000 --- a/src/sim/controller.cc +++ /dev/null @@ -1,69 +0,0 @@ -// 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 . - -#include "controller.h" -#include "ex.h" -#include "response.h" -#include "storage.h" - -Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined) - : Stage(stage) -{ - this->clock_cycle = 1; - this->storage = storage; - this->is_pipelined = is_pipelined; - this->is_empty = true; - this->pc = 0x0; - this->checked_out = {}; - this->gprs = {0}; - this->gprs.at(2) = MEM_WORDS; // set the stack pointer -} - -void Controller::run_for(int number) -{ - int i; - for (i = 0; i < number; ++i) { - try { - this->advance(WAIT); - } catch (HaltException &e) { - break; - } - } -} - -int Controller::get_clock_cycle() { return this->clock_cycle; } - -std::array Controller::get_gprs() { return this->gprs; } - -int Controller::get_pc() { return this->pc; } - -InstrDTO *Controller::advance(Response p) -{ - InstrDTO *r; - r = this->next->advance(p); - ++this->clock_cycle; - - if (r) - this->is_empty = true; - - return r; -} - -void Controller::advance_helper() -{ - // TODO: check halt condition and call UI to refresh -} diff --git a/src/sim/dum.cc b/src/sim/dum.cc deleted file mode 100644 index fd3b7a6..0000000 --- a/src/sim/dum.cc +++ /dev/null @@ -1,38 +0,0 @@ -// 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 . - -#include "dum.h" -#include "instrDTO.h" -#include "response.h" -#include "stage.h" - -InstrDTO *DUM::advance(Response p) -{ - InstrDTO *r = nullptr; - - if (this->curr_instr && p == WAIT) { - r = new InstrDTO(*this->curr_instr); - delete this->curr_instr; - curr_instr = nullptr; - } - - return r; -} - -void DUM::advance_helper() {} - -void DUM::set_curr_instr(InstrDTO *d) { this->curr_instr = d; } diff --git a/src/sim/ex.cc b/src/sim/ex.cc deleted file mode 100644 index 117002c..0000000 --- a/src/sim/ex.cc +++ /dev/null @@ -1,452 +0,0 @@ -// 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 . - -#include "ex.h" -#include "instrDTO.h" -#include "pipe_spec.h" -#include "response.h" -#include "stage.h" -#include - -// clang-format off -#define INIT_INSTRUCTION(mnemonic, body) \ - {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \ - body; \ - }} -// clang-format on - -EX::EX(Stage *stage) : Stage(stage) -{ - instr_map = { - - /* R type instructions */ - INIT_INSTRUCTION( - ADD, - { - this->set_condition(OF, ADDITION_OF_GUARD(s1, s2)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s2)); - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SUB, - { - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s2)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s2)); - s1 = s1 - s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - MUL, - { - this->set_condition(OF, MULTIPLICATION_OF_GUARD(s1, s2)); - this->set_condition(UF, MULTIPLICATION_UF_GUARD(s1, s2)); - s1 = s1 * s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - QUOT, - { - this->handle_divide(s1, s2, false); - (void)pc; - (void)s3; - }), - - INIT_INSTRUCTION( - REM, - { - this->handle_divide(s1, s2, true); - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SFTR, - { - s1 = s1 >> s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - SFTL, - { - s1 = s1 << s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - AND, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 & s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - OR, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 | s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - NOT, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = ~s1; - (void)pc; - (void)s3; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - XOR, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 ^ s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - ADDV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - SUBV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - MULV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - DIVV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - CMP, - { - (s1 > s2) ? this->set_condition(GT, true) - : this->set_condition(GT, false); - (s1 == s2) ? this->set_condition(EQ, true) - : this->set_condition(EQ, false); - (void)pc; - (void)s3; - }), - - INIT_INSTRUCTION( - CEV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - /* I type instructions */ - INIT_INSTRUCTION( - LOAD, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - LOADV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - INIT_INSTRUCTION( - ADDI, - { - this->set_condition(OF, ADDITION_OF_GUARD(s1, s3)); - this->set_condition(UF, ADDITION_UF_GUARD(s1, s3)); - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SUBI, - { - this->set_condition(OF, SUBTRACTION_OF_GUARD(s1, s3)); - this->set_condition(UF, SUBTRACTION_UF_GUARD(s1, s3)); - s1 = s1 - s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SFTRI, - { - s1 = s1 >> s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - SFTLI, - { - s1 = s1 << s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - ANDI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 & s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - ORI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 | s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - XORI, - { - this->set_condition(OF, false); - this->set_condition(UF, false); - s1 = s1 ^ s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - STORE, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - STOREV, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - /* J type instructions */ - INIT_INSTRUCTION( - JMP, - { - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - JRL, - { - s1 = pc + s2; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - JAL, - { - s1 = s1 + s2; - (void)pc; - (void)s3; - (void)this; - }), - - INIT_INSTRUCTION( - BEQ, - { - (this->get_condition(EQ)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BGT, - { - (this->get_condition(GT)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BUF, - { - (this->get_condition(UF)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - BOF, - { - (this->get_condition(OF)) ? s1 = pc + s2 : s1 = -1; - (void)s3; - }), - - INIT_INSTRUCTION( - PUSH, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - POP, - { - s1 = s1 + s3; - (void)pc; - (void)s2; - (void)this; - }), - - INIT_INSTRUCTION( - RET, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - - /* NOP */ - INIT_INSTRUCTION( - NOP, - { - (void)pc; - (void)s3; - (void)s2; - (void)s1; - (void)this; - }), - }; -} - -void EX::advance_helper() -{ - signed int s1, s2, s3; - unsigned int pc; - Mnemonic m; - - m = this->curr_instr->get_mnemonic(); - s1 = this->curr_instr->get_s1(); - s2 = this->curr_instr->get_s2(); - s3 = this->curr_instr->get_s3(); - pc = this->curr_instr->get_pc(); - - this->instr_map[m](s1, s2, s3, pc); - - this->curr_instr->set_s1(s1); - this->status = OK; -} - -void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) -{ - this->set_condition(OF, DIVISION_OF_GUARD(s1, s2)); - this->set_condition(UF, false); - if (s2 == 0) { - // handle everything here - this->curr_instr->set_s1(MAX_INT); - this->status = OK; - throw HaltException(); - } else if ((s1 == -(MAX_INT)-1) && s2 == -1) { - // undefined in C++ - s1 = -(MAX_INT)-1; - } else { - s1 = (is_mod) ? (s1 % s2) : (s1 / s2); - } -} diff --git a/src/sim/id.cc b/src/sim/id.cc deleted file mode 100644 index b2bc0e5..0000000 --- a/src/sim/id.cc +++ /dev/null @@ -1,230 +0,0 @@ -// 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 . - -#include "id.h" -#include "instr.h" -#include "instrDTO.h" -#include "logger.h" -#include "response.h" -#include "stage.h" - -ID::ID(Stage *stage) : Stage(stage) { } - -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->set_checked_out(v); - } - v = this->dereference_register(v); -} - -void ID::advance_helper() -{ - signed int s1, s2, s3; - Mnemonic m; - Type t; - - if (curr_instr->get_mnemonic() == NOP) - this->status = OK; - else { - s1 = curr_instr->get_instr_bits(); - get_instr_fields(s1, s2, s3, m, t); - if (this->status == OK) { - curr_instr->set_s1(s1); - curr_instr->set_s2(s2); - curr_instr->set_s3(s3); - curr_instr->set_mnemonic(m); - curr_instr->set_type(t); - } - } -} - -void ID::get_instr_fields( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) -{ - unsigned int type; - this->split_instr(s1, type, m); - - switch (type) { - case 0b00: - t = R; - this->decode_R_type(s1, s2, s3, m); - break; - case 0b01: - t = I; - this->decode_I_type(s1, s2, s3, m); - break; - case 0b10: - t = J; - this->decode_J_type(s1, s2, s3, m); - break; - case 0b11: - t = INV; - 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); - } - -} - -std::vector ID::stage_info() -{ - std::vector info; - if (this->curr_instr) { - info.push_back(this->curr_instr->is_squashed()); - info.push_back(this->curr_instr->get_instr_bits()); - } - return info; -} diff --git a/src/sim/if.cc b/src/sim/if.cc deleted file mode 100644 index 054c77c..0000000 --- a/src/sim/if.cc +++ /dev/null @@ -1,65 +0,0 @@ -// 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 . - -#include "if.h" -#include "instrDTO.h" -#include "response.h" -#include "stage.h" - -InstrDTO *IF::advance(Response p) -{ - InstrDTO *r = nullptr; - - this->advance_helper(); - if (this->curr_instr != nullptr && p == WAIT) { - // don't increment PC if the PC was just set by wb - if (this->curr_instr->is_squashed() != 1) - ++this->pc; - r = new InstrDTO(*this->curr_instr); - delete curr_instr; - curr_instr = nullptr; - } - - return r; -} - -std::vector IF::stage_info() { - std::vector info; - if(this->curr_instr){ - info.push_back(this->curr_instr->is_squashed()); - info.push_back(this->curr_instr->get_instr_bits()); - } - return info; -} - -void IF::advance_helper() -{ - Response r; - int i; - signed int bits; - - if (this->curr_instr == nullptr && (this->is_pipelined || this->is_empty)) { - i = this->storage->read_word(this, this->pc, bits); - r = i ? OK : STALLED; - if (r == OK) { - this->curr_instr = new InstrDTO(); - this->curr_instr->set_instr_bits(bits); - this->curr_instr->set_pc(this->pc); - this->is_empty = false; - } - } -} diff --git a/src/sim/instr.cc b/src/sim/instr.cc deleted file mode 100644 index 9bd951b..0000000 --- a/src/sim/instr.cc +++ /dev/null @@ -1,40 +0,0 @@ -// 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 . - -#include "instr.h" -#include -#include -#include - -namespace instr -{ -const std::unordered_map 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}, -}; -} // namespace instr diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc deleted file mode 100644 index cb093bb..0000000 --- a/src/sim/instrDTO.cc +++ /dev/null @@ -1,70 +0,0 @@ -// 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 . - -#include "instrDTO.h" - -InstrDTO::InstrDTO() -{ - this->instr_bits = 0; - this->checked_out = -1; - this->s1 = 0; - this->s2 = 0; - this->s3 = 0; - this->mnemonic = ADD; - this->type = INV; - this->pc = 0; - this->squashed = 0; -} - -signed int InstrDTO::get_instr_bits() { return this->instr_bits; } - -signed int InstrDTO::get_checked_out() { return this->checked_out; } - -signed int InstrDTO::get_s1() { return this->s1; } - -signed int InstrDTO::get_s2() { return this->s2; } - -signed int InstrDTO::get_s3() { return this->s3; } - -Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } - -Type InstrDTO::get_type() { return this->type; } - -unsigned int InstrDTO::get_pc() { return this->pc; } - -int InstrDTO::is_squashed() { return this->squashed; } - -void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } - -void InstrDTO::set_checked_out(signed int checked_out) -{ - this->checked_out = checked_out; -} - -void InstrDTO::set_s1(signed int s) { this->s1 = s; } - -void InstrDTO::set_s2(signed int s) { this->s2 = s; } - -void InstrDTO::set_s3(signed int s) { this->s3 = s; } - -void InstrDTO::set_mnemonic(Mnemonic m) { this->mnemonic = m; } - -void InstrDTO::set_type(Type t) { this->type = t; } - -void InstrDTO::set_pc(unsigned int pc) { this->pc = pc; } - -void InstrDTO::squash() { this->squashed = 1; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc deleted file mode 100644 index 3df1578..0000000 --- a/src/sim/mm.cc +++ /dev/null @@ -1,60 +0,0 @@ -// 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 . - -#include "mm.h" -#include "instrDTO.h" -#include "response.h" -#include "stage.h" - -void MM::advance_helper() -{ - signed int data; - int i; - - switch (this->curr_instr->get_mnemonic()) { - case LOAD: - i = this->storage->read_word(this, this->curr_instr->get_s1(), data); - this->status = i ? OK : STALLED; - if (this->status == OK) { - this->curr_instr->set_s1(data); - } else - this->status = STALLED; - break; - - case PUSH: - case STORE: - i = this->storage->write_word( - this, this->curr_instr->get_s2(), this->curr_instr->get_s1()); - this->status = i ? OK : STALLED; - if (this->status != OK) { - this->status = STALLED; - } - break; - - case POP: - i = this->storage->read_word(this, this->curr_instr->get_s3(), data); - this->status = i ? OK : STALLED; - if (this->status == OK) { - this->curr_instr->set_s3(data); - } else - this->status = STALLED; - break; - - default: - this->status = OK; - } -} diff --git a/src/sim/stage.cc b/src/sim/stage.cc deleted file mode 100644 index b7be595..0000000 --- a/src/sim/stage.cc +++ /dev/null @@ -1,130 +0,0 @@ -// 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 . - -#include "stage.h" -#include -#include - -Stage::Stage(Stage *next) -{ - this->next = next; - this->curr_instr = nullptr; - this->status = WAIT; -} - -Stage::~Stage() { delete this->next; }; - -std::array Stage::gprs; -std::array Stage::vrs; -std::deque Stage::checked_out; -unsigned int Stage::pc; -Storage *Stage::storage; -bool Stage::is_pipelined; -bool Stage::is_empty; -int Stage::clock_cycle; - -bool Stage::get_condition(CC c) { return (this->gprs[3] >> c) & 1; } - -InstrDTO *Stage::advance(Response p) -{ - InstrDTO *r = nullptr; - InstrDTO *s = nullptr; - Response n; - - if (this->curr_instr && this->curr_instr->is_squashed() == 1) - this->status = OK; - if (this->curr_instr && this->status != OK) { - this->advance_helper(); - } - if (this->status == OK && p == WAIT && this->curr_instr) { - // mutual consent - r = new InstrDTO(*this->curr_instr); - delete curr_instr; - curr_instr = nullptr; - this->status = WAIT; - } - - n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; - s = this->next->advance(n); - if (s) - this->curr_instr = s; - return r; -} - -std::vector Stage::stage_info() -{ - std::vector info; - if (this->curr_instr) { - info.push_back(this->curr_instr->get_mnemonic()); - info.push_back(this->curr_instr->is_squashed()); - info.push_back(this->curr_instr->get_s1()); - info.push_back(this->curr_instr->get_s2()); - info.push_back(this->curr_instr->get_s3()); - } - return info; -} - -void Stage::set_condition(CC c, bool v) -{ - if (v) - this->gprs[3] = this->gprs[3] | 1 << c; - else - this->gprs[3] = this->gprs[3] & ~(1 << c); -} - -signed int Stage::dereference_register(signed int v) -{ - signed int r; - - if (v < 0 || v >= GPR_NUM + V_NUM) { - throw std::out_of_range( - "instruction tried to access register which does not exist"); - } - - r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[v]; - return r; -} - -void Stage::store_register(signed int v, signed int d) -{ - if (v < 0 || v >= GPR_NUM + V_NUM) { - throw std::out_of_range( - "instruction tried to access register which does not exist"); - } - - if (v >= GPR_NUM) - this->vrs[v % GPR_NUM] = d; - else - this->gprs[v] = d; -} - -bool Stage::is_checked_out(signed int r) -{ - return std::find(this->checked_out.begin(), this->checked_out.end(), r) != - this->checked_out.end(); -} - -void Stage::squash() -{ - if (curr_instr) { - this->curr_instr->squash(); - this->status = OK; - } - if (this->next) { - this->next->squash(); - } -} diff --git a/src/sim/wb.cc b/src/sim/wb.cc deleted file mode 100644 index 55591b6..0000000 --- a/src/sim/wb.cc +++ /dev/null @@ -1,75 +0,0 @@ -// 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 . - -#include "wb.h" -#include "instrDTO.h" -#include "response.h" -#include "stage.h" -#include -#include - -void WB::advance_helper() -{ - if (this->curr_instr->get_mnemonic() != NOP && - this->curr_instr->get_type() != INV) { - if (this->curr_instr->get_checked_out() > 0) - this->write_handler(); - else if (this->should_jump()) - this->jump_handler(); - } - this->status = OK; -} - -void WB::write_handler() -{ - signed int reg; - - if (this->checked_out.size() < 1) - throw std::runtime_error("instruction tried to pop a register out of " - "an empty queue during writeback."); - - if (this->curr_instr->get_mnemonic() == POP) { - // POP performs a second register write - reg = this->checked_out.front(); - this->checked_out.pop_front(); - this->store_register(reg, this->curr_instr->get_s3()); - } - - this->checked_out.pop_front(); - reg = this->curr_instr->get_checked_out(); - this->store_register(reg, this->curr_instr->get_s1()); - -} - -void WB::jump_handler() -{ - if (this->curr_instr->get_s1() > 0) { - if (this->curr_instr->get_mnemonic() == JAL) - this->gprs[1] = this->curr_instr->get_pc() + 1;; - this->pc = this->curr_instr->get_s1(); - this->checked_out = {}; - this->next->squash(); - } -} - -bool WB::should_jump() -{ - Type t; - - t = this->curr_instr->get_type(); - return t == J; -} diff --git a/src/stage.cc b/src/stage.cc new file mode 100644 index 0000000..b7be595 --- /dev/null +++ b/src/stage.cc @@ -0,0 +1,130 @@ +// 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 . + +#include "stage.h" +#include +#include + +Stage::Stage(Stage *next) +{ + this->next = next; + this->curr_instr = nullptr; + this->status = WAIT; +} + +Stage::~Stage() { delete this->next; }; + +std::array Stage::gprs; +std::array Stage::vrs; +std::deque Stage::checked_out; +unsigned int Stage::pc; +Storage *Stage::storage; +bool Stage::is_pipelined; +bool Stage::is_empty; +int Stage::clock_cycle; + +bool Stage::get_condition(CC c) { return (this->gprs[3] >> c) & 1; } + +InstrDTO *Stage::advance(Response p) +{ + InstrDTO *r = nullptr; + InstrDTO *s = nullptr; + Response n; + + if (this->curr_instr && this->curr_instr->is_squashed() == 1) + this->status = OK; + if (this->curr_instr && this->status != OK) { + this->advance_helper(); + } + if (this->status == OK && p == WAIT && this->curr_instr) { + // mutual consent + r = new InstrDTO(*this->curr_instr); + delete curr_instr; + curr_instr = nullptr; + this->status = WAIT; + } + + n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; + s = this->next->advance(n); + if (s) + this->curr_instr = s; + return r; +} + +std::vector Stage::stage_info() +{ + std::vector info; + if (this->curr_instr) { + info.push_back(this->curr_instr->get_mnemonic()); + info.push_back(this->curr_instr->is_squashed()); + info.push_back(this->curr_instr->get_s1()); + info.push_back(this->curr_instr->get_s2()); + info.push_back(this->curr_instr->get_s3()); + } + return info; +} + +void Stage::set_condition(CC c, bool v) +{ + if (v) + this->gprs[3] = this->gprs[3] | 1 << c; + else + this->gprs[3] = this->gprs[3] & ~(1 << c); +} + +signed int Stage::dereference_register(signed int v) +{ + signed int r; + + if (v < 0 || v >= GPR_NUM + V_NUM) { + throw std::out_of_range( + "instruction tried to access register which does not exist"); + } + + r = (v >= GPR_NUM) ? this->vrs[v % GPR_NUM] : this->gprs[v]; + return r; +} + +void Stage::store_register(signed int v, signed int d) +{ + if (v < 0 || v >= GPR_NUM + V_NUM) { + throw std::out_of_range( + "instruction tried to access register which does not exist"); + } + + if (v >= GPR_NUM) + this->vrs[v % GPR_NUM] = d; + else + this->gprs[v] = d; +} + +bool Stage::is_checked_out(signed int r) +{ + return std::find(this->checked_out.begin(), this->checked_out.end(), r) != + this->checked_out.end(); +} + +void Stage::squash() +{ + if (curr_instr) { + this->curr_instr->squash(); + this->status = OK; + } + if (this->next) { + this->next->squash(); + } +} diff --git a/src/utils/response.cc b/src/utils/response.cc deleted file mode 100644 index d56419a..0000000 --- a/src/utils/response.cc +++ /dev/null @@ -1,25 +0,0 @@ -// 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 . - -#include "response.h" -#include - -std::ostream &operator<<(std::ostream &os, Response r) -{ - const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; - return os << nameR[r]; -} diff --git a/src/wb.cc b/src/wb.cc new file mode 100644 index 0000000..55591b6 --- /dev/null +++ b/src/wb.cc @@ -0,0 +1,75 @@ +// 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 . + +#include "wb.h" +#include "instrDTO.h" +#include "response.h" +#include "stage.h" +#include +#include + +void WB::advance_helper() +{ + if (this->curr_instr->get_mnemonic() != NOP && + this->curr_instr->get_type() != INV) { + if (this->curr_instr->get_checked_out() > 0) + this->write_handler(); + else if (this->should_jump()) + this->jump_handler(); + } + this->status = OK; +} + +void WB::write_handler() +{ + signed int reg; + + if (this->checked_out.size() < 1) + throw std::runtime_error("instruction tried to pop a register out of " + "an empty queue during writeback."); + + if (this->curr_instr->get_mnemonic() == POP) { + // POP performs a second register write + reg = this->checked_out.front(); + this->checked_out.pop_front(); + this->store_register(reg, this->curr_instr->get_s3()); + } + + this->checked_out.pop_front(); + reg = this->curr_instr->get_checked_out(); + this->store_register(reg, this->curr_instr->get_s1()); + +} + +void WB::jump_handler() +{ + if (this->curr_instr->get_s1() > 0) { + if (this->curr_instr->get_mnemonic() == JAL) + this->gprs[1] = this->curr_instr->get_pc() + 1;; + this->pc = this->curr_instr->get_s1(); + this->checked_out = {}; + this->next->squash(); + } +} + +bool WB::should_jump() +{ + Type t; + + t = this->curr_instr->get_type(); + return t == J; +} -- cgit v1.2.3