From 1bbc5b157e16dae032b5e44a7dcf009766eb9ca5 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 20:48:31 -0400 Subject: Fix bug where checking for multiplication overflow resulted in FPE --- inc/ex.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/inc/ex.h b/inc/ex.h index f7428da..c356543 100644 --- a/inc/ex.h +++ b/inc/ex.h @@ -41,7 +41,7 @@ ((b < 0) && (a < 0) && (a < MAX_INT / b))) #define MULTIPLICATION_UF_GUARD(a, b) \ - (b != 0) && \ + (b != 0) && (b != -1) && \ (((b > 0) && (a < 0) && (a < (-(MAX_INT)-1) / b)) || \ ((b < 0) && (a > 0) && (a > (-(MAX_INT)-1) / b))) -- cgit v1.2.3 From 95d09e12792cf5ececd32b8dc84f2cd090c496ef Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 20:49:26 -0400 Subject: Remove the accessor object --- inc/accessor.h | 35 ----------------------------------- inc/dum.h | 7 +------ inc/id.h | 6 +----- inc/if.h | 8 +------- inc/instrDTO.h | 1 - inc/mm.h | 7 +------ inc/stage.h | 5 ----- inc/wb.h | 7 +------ src/sim/controller.cc | 2 -- src/sim/dum.cc | 8 +------- src/sim/ex.cc | 2 -- src/sim/id.cc | 3 +-- src/sim/if.cc | 3 --- src/sim/instrDTO.cc | 1 - src/sim/mm.cc | 3 --- src/sim/stage.cc | 6 ------ src/sim/wb.cc | 3 --- src/utils/accessor.cc | 27 --------------------------- 18 files changed, 7 insertions(+), 127 deletions(-) delete mode 100644 inc/accessor.h delete mode 100644 src/utils/accessor.cc diff --git a/inc/accessor.h b/inc/accessor.h deleted file mode 100644 index 67a68b9..0000000 --- a/inc/accessor.h +++ /dev/null @@ -1,35 +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 . - -#ifndef ACCESSOR_H -#define ACCESSOR_H -#include - -enum Accessor { - IDLE, - WRITE, - MEM, - EXEC, - DCDE, - FETCH, - L1CACHE, - SIDE, -}; - -std::ostream &operator<<(std::ostream &os, Accessor a); - -#endif /* ACCESSOR_H_INCLUDED */ diff --git a/inc/dum.h b/inc/dum.h index 4a3069a..e5ec740 100644 --- a/inc/dum.h +++ b/inc/dum.h @@ -27,12 +27,7 @@ class DUM : public Stage { public: - /** - * Constructor. - * @param The next stage in the pipeline. - * @return A newly allocated DUM object. - */ - DUM(Stage *next); + using Stage::Stage; InstrDTO *advance(Response p) override; diff --git a/inc/id.h b/inc/id.h index d6c108a..a10ad49 100644 --- a/inc/id.h +++ b/inc/id.h @@ -25,12 +25,8 @@ class ID : public Stage { public: - /** - * Constructor. - * @param The next stage in the pipeline. - * @return A newly allocated ID object. - */ ID(Stage *next); + using Stage::Stage; using Stage::advance; /* The following methods are made public so that they may be tested, and are diff --git a/inc/if.h b/inc/if.h index b430dbd..c374145 100644 --- a/inc/if.h +++ b/inc/if.h @@ -17,7 +17,6 @@ #ifndef IF_H #define IF_H -#include "accessor.h" #include "instrDTO.h" #include "response.h" #include "stage.h" @@ -25,12 +24,7 @@ class IF : public Stage { public: - /** - * Constructor. - * @param The next stage in the pipeline. - * @return A newly allocated IF object. - */ - IF(Stage *next); + using Stage::Stage; InstrDTO *advance(Response p) override; diff --git a/inc/instrDTO.h b/inc/instrDTO.h index d4af389..e6c9852 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -17,7 +17,6 @@ #ifndef INSTRDTO_H #define INSTRDTO_H -#include "accessor.h" #include "instr.h" #include #include diff --git a/inc/mm.h b/inc/mm.h index aec1cdd..230b258 100644 --- a/inc/mm.h +++ b/inc/mm.h @@ -24,12 +24,7 @@ class MM : public Stage { public: - /** - * Constructor. - * @param The next stage in the pipeline. - * @return A newly allocated MM object. - */ - MM(Stage *next); + using Stage::Stage; using Stage::advance; private: diff --git a/inc/stage.h b/inc/stage.h index 448c61a..745e0ff 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -17,7 +17,6 @@ #ifndef STAGE_H #define STAGE_H -#include "accessor.h" #include "instrDTO.h" #include "pipe_spec.h" #include "response.h" @@ -111,10 +110,6 @@ class Stage * @return the value in the associated register. */ signed int dereference_register(signed int v); - /** - * The name of the pipeline stage. - */ - Accessor id; /** * The shared pool of general-purpose integer registers. */ diff --git a/inc/wb.h b/inc/wb.h index c3547c3..d3a1b93 100644 --- a/inc/wb.h +++ b/inc/wb.h @@ -24,12 +24,7 @@ class WB : public Stage { public: - /** - * Constructor. - * @param The next stage in the pipeline. - * @return A newly allocated WB object. - */ - WB(Stage *next); + using Stage::Stage; using Stage::advance; private: diff --git a/src/sim/controller.cc b/src/sim/controller.cc index 59fbbb7..1c379ec 100644 --- a/src/sim/controller.cc +++ b/src/sim/controller.cc @@ -31,8 +31,6 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined) this->checked_out = {}; this->gprs = {0}; this->gprs.at(2) = MEM_WORDS; // set the stack pointer - // grant side-door access - this->id = SIDE; } void Controller::run_for(int number) diff --git a/src/sim/dum.cc b/src/sim/dum.cc index 744c110..fd3b7a6 100644 --- a/src/sim/dum.cc +++ b/src/sim/dum.cc @@ -16,13 +16,10 @@ // along with this program. If not, see . #include "dum.h" -#include "accessor.h" #include "instrDTO.h" #include "response.h" #include "stage.h" -DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; } - InstrDTO *DUM::advance(Response p) { InstrDTO *r = nullptr; @@ -38,7 +35,4 @@ InstrDTO *DUM::advance(Response p) void DUM::advance_helper() {} -void DUM::set_curr_instr(InstrDTO *d) -{ - this->curr_instr = d; -} +void DUM::set_curr_instr(InstrDTO *d) { this->curr_instr = d; } diff --git a/src/sim/ex.cc b/src/sim/ex.cc index d345ecf..117002c 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -16,7 +16,6 @@ // along with this program. If not, see . #include "ex.h" -#include "accessor.h" #include "instrDTO.h" #include "pipe_spec.h" #include "response.h" @@ -32,7 +31,6 @@ EX::EX(Stage *stage) : Stage(stage) { - this->id = EXEC; instr_map = { /* R type instructions */ diff --git a/src/sim/id.cc b/src/sim/id.cc index cdbaba9..b2bc0e5 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -16,14 +16,13 @@ // along with this program. If not, see . #include "id.h" -#include "accessor.h" #include "instr.h" #include "instrDTO.h" #include "logger.h" #include "response.h" #include "stage.h" -ID::ID(Stage *stage) : Stage(stage) { this->id = DCDE; } +ID::ID(Stage *stage) : Stage(stage) { } void ID::split_instr(signed int &raw, unsigned int &type, Mnemonic &m) { diff --git a/src/sim/if.cc b/src/sim/if.cc index e8e7272..054c77c 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -16,13 +16,10 @@ // along with this program. If not, see . #include "if.h" -#include "accessor.h" #include "instrDTO.h" #include "response.h" #include "stage.h" -IF::IF(Stage *stage) : Stage(stage) { this->id = FETCH; } - InstrDTO *IF::advance(Response p) { InstrDTO *r = nullptr; diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index 00b6d5f..cb093bb 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -16,7 +16,6 @@ // along with this program. If not, see . #include "instrDTO.h" -#include "accessor.h" InstrDTO::InstrDTO() { diff --git a/src/sim/mm.cc b/src/sim/mm.cc index e1057d5..3df1578 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -16,13 +16,10 @@ // along with this program. If not, see . #include "mm.h" -#include "accessor.h" #include "instrDTO.h" #include "response.h" #include "stage.h" -MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } - void MM::advance_helper() { signed int data; diff --git a/src/sim/stage.cc b/src/sim/stage.cc index 35c6936..b7be595 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -45,12 +45,6 @@ InstrDTO *Stage::advance(Response p) InstrDTO *s = nullptr; Response n; - // std::cout << "advance: " << this->id << ": " << this->curr_instr << "?: " - // << p << ": " << this->checked_out.size() << ": "; if (curr_instr) - // std::cout << curr_instr->get_mnemonic(); - // for (long unsigned int i = 0; i < this->checked_out.size(); ++i) - // std::cout << this->checked_out[i] << " "; - // std::cout << std::endl; if (this->curr_instr && this->curr_instr->is_squashed() == 1) this->status = OK; if (this->curr_instr && this->status != OK) { diff --git a/src/sim/wb.cc b/src/sim/wb.cc index 0348b51..55591b6 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -16,15 +16,12 @@ // along with this program. If not, see . #include "wb.h" -#include "accessor.h" #include "instrDTO.h" #include "response.h" #include "stage.h" #include #include -WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } - void WB::advance_helper() { if (this->curr_instr->get_mnemonic() != NOP && diff --git a/src/utils/accessor.cc b/src/utils/accessor.cc deleted file mode 100644 index c49a2b2..0000000 --- a/src/utils/accessor.cc +++ /dev/null @@ -1,27 +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 "accessor.h" -#include - -std::ostream &operator<<(std::ostream &os, Accessor a) -{ - const std::string nameA[] = { - "IDLE", "WRITE", "MEM", "EXEC", "DCDE", "FETCH", "L1CACHE", "SIDE", - }; - return os << nameA[a]; -} -- cgit v1.2.3 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 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 From 74b24d15eb1fe48a8e221a0bc061107d6b85d659 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 21:28:21 -0400 Subject: Add definition for size of vector register --- inc/id.h | 1 - inc/pipe_spec.h | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/inc/id.h b/inc/id.h index a10ad49..dabf206 100644 --- a/inc/id.h +++ b/inc/id.h @@ -25,7 +25,6 @@ class ID : public Stage { public: - ID(Stage *next); using Stage::Stage; using Stage::advance; diff --git a/inc/pipe_spec.h b/inc/pipe_spec.h index 0433f23..7d65637 100644 --- a/inc/pipe_spec.h +++ b/inc/pipe_spec.h @@ -39,6 +39,11 @@ */ #define V_NUM 8 +/** + * The size, in 32-bit integers, of a vector register. + */ +#define V_R_LIMIT 8 + /** * The number of bits to specify an instruction type */ -- cgit v1.2.3 From 302bbdc7ac18cd355f9f081cae202f5434427262 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 23:39:14 -0400 Subject: Use a struct for InstrDTO --- inc/instrDTO.h | 126 ++++++++++---------------------------------------------- src/ex.cc | 14 +++---- src/id.cc | 20 ++++----- src/if.cc | 14 ++++--- src/instrDTO.cc | 70 ------------------------------- src/mm.cc | 14 ++++--- src/stage.cc | 14 +++---- src/wb.cc | 24 +++++------ tests/ex.cc | 98 +++++++++++++++++++++---------------------- tests/id.cc | 48 ++++++++++----------- tests/if.cc | 8 ++-- 11 files changed, 152 insertions(+), 298 deletions(-) delete mode 100644 src/instrDTO.cc diff --git a/inc/instrDTO.h b/inc/instrDTO.h index e6c9852..7775b20 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -22,127 +22,45 @@ #include #include -class InstrDTO -{ - public: - /** - * Constructor. - */ - InstrDTO(); - ~InstrDTO() = default; - - int get_id_cycle(); - /** - * @return instr_bits - */ - signed int get_instr_bits(); - /** - * @return checked_out - */ - signed int get_checked_out(); - /** - * @return s1 - */ - signed int get_s1(); - /** - * @return s2 - */ - signed int get_s2(); - /** - * @return s3 - */ - signed int get_s3(); - /** - * @return the mnemonic of the instruction - */ - Mnemonic get_mnemonic(); - /** - * @return the type of the instruction - */ - Type get_type(); - /** - * @return the program counter at the time this instruction was fetched - */ - unsigned int get_pc(); - /** - * @return 1 if this instruction is invalid, 0 otherwise - */ - int is_squashed(); - - /** - * @param instr_bits - */ - void set_instr_bits(signed int); - /** - * @param checked_out - */ - void set_checked_out(signed int); - /** - * @param s1 - */ - void set_s1(signed int); - /** - * @param s2 - */ - void set_s2(signed int); - /** - * @param s3 - */ - void set_s3(signed int); - /** - * @param the mnemonic of the instruction - */ - void set_mnemonic(Mnemonic); +struct U_INT_TYPE { + signed int slot_one; + signed int slot_two; + signed int slot_three; +}; - /** - * @param the type of the instruction - */ - void set_type(Type); - /** - * @param the program counter at the time this instruction was fetched - */ - void set_pc(unsigned int pc); - /** - * squashes this instruction - */ - void squash(); +struct V_TYPE { +}; - private: +struct InstrDTO { /** - * The raw bits encoding the instruction. + * If this instruction is squashed or not. */ - signed int instr_bits; + unsigned int is_squashed : 1; /** - * The register, if any, this instruction has checked out. A checked out - * register cannot be checked out by another register. This prevents RAW - * conflicts. + * Optional slot for holding the Instruction Bits */ - signed int checked_out; + signed int slot_A; /** - * Slots in this instruction, for storing temporary registers, immediates, - * or other. - * Some instruction types may use these differently. - * The `oper` function is in charge of knowing how to parse these. + * Optional slot for holding PC */ - signed int s1; - signed int s2; - signed int s3; + signed int slot_B; /** - * The mnemonic of the operation. + * The mnemonic of the instruction. */ Mnemonic mnemonic; + // TODO delete me /** * Type of the instruction */ Type type; /** - * The PC of the instruction + * The register this instruction checks out. */ - unsigned int pc; - /** - * If this instruction was made dead - */ - unsigned int squashed; + signed int checked_out; + union { + struct U_INT_TYPE integer; + struct V_TYPE vector; + } operands; }; #endif /* INSTRDTO_H_INCLUDED */ diff --git a/src/ex.cc b/src/ex.cc index 117002c..eac24ff 100644 --- a/src/ex.cc +++ b/src/ex.cc @@ -422,15 +422,15 @@ void EX::advance_helper() 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(); + m = this->curr_instr->mnemonic; + s1 = this->curr_instr->operands.integer.slot_one; + s2 = this->curr_instr->operands.integer.slot_two; + s3 = this->curr_instr->operands.integer.slot_three; + pc = this->curr_instr->slot_B; this->instr_map[m](s1, s2, s3, pc); - this->curr_instr->set_s1(s1); + this->curr_instr->operands.integer.slot_one = s1; this->status = OK; } @@ -440,7 +440,7 @@ void EX::handle_divide(signed int &s1, signed int s2, bool is_mod) this->set_condition(UF, false); if (s2 == 0) { // handle everything here - this->curr_instr->set_s1(MAX_INT); + this->curr_instr->operands.integer.slot_one = MAX_INT; this->status = OK; throw HaltException(); } else if ((s1 == -(MAX_INT)-1) && s2 == -1) { diff --git a/src/id.cc b/src/id.cc index 97bd844..14fe595 100644 --- a/src/id.cc +++ b/src/id.cc @@ -57,7 +57,7 @@ void ID::write_guard(signed int &v) // 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); + this->curr_instr->checked_out = v; } v = this->dereference_register(v); } @@ -68,17 +68,17 @@ void ID::advance_helper() Mnemonic m; Type t; - if (curr_instr->get_mnemonic() == NOP) + if (curr_instr->mnemonic == NOP) this->status = OK; else { - s1 = curr_instr->get_instr_bits(); + s1 = curr_instr->slot_A; 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); + 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; + curr_instr->type = t; } } } @@ -221,8 +221,8 @@ 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()); + info.push_back(this->curr_instr->is_squashed); + info.push_back(this->curr_instr->slot_A); } return info; } diff --git a/src/if.cc b/src/if.cc index 054c77c..fd795c7 100644 --- a/src/if.cc +++ b/src/if.cc @@ -27,7 +27,7 @@ InstrDTO *IF::advance(Response p) 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) + if (this->curr_instr->is_squashed != 1) ++this->pc; r = new InstrDTO(*this->curr_instr); delete curr_instr; @@ -40,8 +40,8 @@ InstrDTO *IF::advance(Response p) 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()); + info.push_back(this->curr_instr->is_squashed); + info.push_back(this->curr_instr->slot_A); } return info; } @@ -57,8 +57,12 @@ void IF::advance_helper() 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->curr_instr->slot_A = bits; + this->curr_instr->slot_B = this->pc; + this->curr_instr->type = INV; + this->curr_instr->is_squashed = 0; + this->curr_instr->checked_out = -1; + this->curr_instr->mnemonic = ADD; this->is_empty = false; } } diff --git a/src/instrDTO.cc b/src/instrDTO.cc deleted file mode 100644 index cb093bb..0000000 --- a/src/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/mm.cc b/src/mm.cc index 3df1578..ac77433 100644 --- a/src/mm.cc +++ b/src/mm.cc @@ -25,12 +25,13 @@ void MM::advance_helper() signed int data; int i; - switch (this->curr_instr->get_mnemonic()) { + switch (this->curr_instr->mnemonic) { case LOAD: - i = this->storage->read_word(this, this->curr_instr->get_s1(), data); + i = this->storage->read_word( + this, this->curr_instr->operands.integer.slot_one, data); this->status = i ? OK : STALLED; if (this->status == OK) { - this->curr_instr->set_s1(data); + this->curr_instr->operands.integer.slot_one = data; } else this->status = STALLED; break; @@ -38,7 +39,8 @@ void MM::advance_helper() case PUSH: case STORE: i = this->storage->write_word( - this, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + 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; @@ -46,10 +48,10 @@ void MM::advance_helper() break; case POP: - i = this->storage->read_word(this, this->curr_instr->get_s3(), data); + i = this->storage->read_word(this, this->curr_instr->operands.integer.slot_three, data); this->status = i ? OK : STALLED; if (this->status == OK) { - this->curr_instr->set_s3(data); + this->curr_instr->operands.integer.slot_three = data; } else this->status = STALLED; break; diff --git a/src/stage.cc b/src/stage.cc index b7be595..e5a4333 100644 --- a/src/stage.cc +++ b/src/stage.cc @@ -45,7 +45,7 @@ InstrDTO *Stage::advance(Response p) InstrDTO *s = nullptr; Response n; - if (this->curr_instr && this->curr_instr->is_squashed() == 1) + if (this->curr_instr && this->curr_instr->is_squashed == 1) this->status = OK; if (this->curr_instr && this->status != OK) { this->advance_helper(); @@ -69,11 +69,11 @@ 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()); + info.push_back(this->curr_instr->mnemonic); + info.push_back(this->curr_instr->is_squashed); + info.push_back(this->curr_instr->operands.integer.slot_one); + info.push_back(this->curr_instr->operands.integer.slot_two); + info.push_back(this->curr_instr->operands.integer.slot_three); } return info; } @@ -121,7 +121,7 @@ bool Stage::is_checked_out(signed int r) void Stage::squash() { if (curr_instr) { - this->curr_instr->squash(); + this->curr_instr->is_squashed = 1; this->status = OK; } if (this->next) { diff --git a/src/wb.cc b/src/wb.cc index 55591b6..08d512b 100644 --- a/src/wb.cc +++ b/src/wb.cc @@ -24,9 +24,9 @@ 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) + if (this->curr_instr->mnemonic != NOP && + this->curr_instr->type != INV) { + if (this->curr_instr->checked_out > 0) this->write_handler(); else if (this->should_jump()) this->jump_handler(); @@ -42,25 +42,25 @@ void WB::write_handler() throw std::runtime_error("instruction tried to pop a register out of " "an empty queue during writeback."); - if (this->curr_instr->get_mnemonic() == POP) { + if (this->curr_instr->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->store_register(reg, this->curr_instr->operands.integer.slot_three); } this->checked_out.pop_front(); - reg = this->curr_instr->get_checked_out(); - this->store_register(reg, this->curr_instr->get_s1()); + reg = this->curr_instr->checked_out; + this->store_register(reg, this->curr_instr->operands.integer.slot_one); } 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(); + if (this->curr_instr->operands.integer.slot_one > 0) { + if (this->curr_instr->mnemonic == JAL) + this->gprs[1] = this->curr_instr->slot_B + 1;; + this->pc = this->curr_instr->operands.integer.slot_one; this->checked_out = {}; this->next->squash(); } @@ -70,6 +70,6 @@ bool WB::should_jump() { Type t; - t = this->curr_instr->get_type(); + t = this->curr_instr->type; return t == J; } diff --git a/tests/ex.cc b/tests/ex.cc index 400916e..1fc333e 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -27,10 +27,10 @@ class EXFixture execute_instr(signed int s1, signed int s2, signed int s3, Mnemonic m) { InstrDTO *i = new InstrDTO(); - i->set_s1(s1); - i->set_s2(s2); - i->set_s3(s3); - i->set_mnemonic(m); + i->operands.integer.slot_one = s1; + i->operands.integer.slot_two = s2; + i->operands.integer.slot_three = s3; + i->mnemonic = m; this->dum->set_curr_instr(i); i = this->ct->advance(WAIT); @@ -57,7 +57,7 @@ TEST_CASE_METHOD(EXFixture, "ADD within bounds", "[ex]") s1 = 42000, s2 = -41958, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -74,7 +74,7 @@ TEST_CASE_METHOD(EXFixture, "ADD overflow", "[ex]") s1 = MAX_INT, s2 = 1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(i->operands.integer.slot_one == -(MAX_INT)-1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -91,7 +91,7 @@ TEST_CASE_METHOD(EXFixture, "ADD underflow", "[ex]") s1 = -(MAX_INT)-1, s2 = -1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == MAX_INT); + CHECK(i->operands.integer.slot_one == MAX_INT); CHECK(!ct->get_condition(OF)); CHECK(ct->get_condition(UF)); @@ -108,7 +108,7 @@ TEST_CASE_METHOD(EXFixture, "SUB within bounds", "[ex]") s1 = 200, s2 = 131, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); + CHECK(i->operands.integer.slot_one == 69); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -125,7 +125,7 @@ TEST_CASE_METHOD(EXFixture, "SUB overflow", "[ex]") s1 = MAX_INT, s2 = -1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(i->operands.integer.slot_one == -(MAX_INT)-1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -142,7 +142,7 @@ TEST_CASE_METHOD(EXFixture, "SUB underflow", "[ex]") s1 = -(MAX_INT)-1, s2 = 1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == MAX_INT); + CHECK(i->operands.integer.slot_one == MAX_INT); CHECK(!ct->get_condition(OF)); CHECK(ct->get_condition(UF)); @@ -159,7 +159,7 @@ TEST_CASE_METHOD(EXFixture, "MUL within bounds", "[ex]") s1 = 200, s2 = 200, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 40000); + CHECK(i->operands.integer.slot_one == 40000); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -176,7 +176,7 @@ TEST_CASE_METHOD(EXFixture, "MUL overflow", "[ex]") s1 = MAX_INT, s2 = MAX_INT, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 1); + CHECK(i->operands.integer.slot_one == 1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -193,7 +193,7 @@ TEST_CASE_METHOD(EXFixture, "MUL underflow", "[ex]") s1 = MAX_INT, s2 = -MAX_INT, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); CHECK(!ct->get_condition(OF)); CHECK(ct->get_condition(UF)); @@ -210,7 +210,7 @@ TEST_CASE_METHOD(EXFixture, "QUOT within bounds", "[ex]") s1 = 2043, s2 = 40, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 51); + CHECK(i->operands.integer.slot_one == 51); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -227,7 +227,7 @@ TEST_CASE_METHOD(EXFixture, "QUOT overflow", "[ex]") s1 = -(MAX_INT)-1, s2 = -1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(i->operands.integer.slot_one == -(MAX_INT)-1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -258,7 +258,7 @@ TEST_CASE_METHOD(EXFixture, "REM within bounds", "[ex]") s1 = 2043, s2 = 40, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 3); + CHECK(i->operands.integer.slot_one == 3); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -289,7 +289,7 @@ TEST_CASE_METHOD(EXFixture, "SFTR within bounds", "[ex]") s1 = 1300, s2 = 6, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 20); + CHECK(i->operands.integer.slot_one == 20); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -314,7 +314,7 @@ TEST_CASE_METHOD(EXFixture, "SFTL within bounds", "[ex]") s1 = 13, s2 = 6, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 832); + CHECK(i->operands.integer.slot_one == 832); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -339,7 +339,7 @@ TEST_CASE_METHOD(EXFixture, "AND", "[ex]") s1 = 1234, s2 = 5678, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 1026); + CHECK(i->operands.integer.slot_one == 1026); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -356,7 +356,7 @@ TEST_CASE_METHOD(EXFixture, "OR", "[ex]") s1 = 1234, s2 = 5678, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 5886); + CHECK(i->operands.integer.slot_one == 5886); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -373,7 +373,7 @@ TEST_CASE_METHOD(EXFixture, "NOT", "[ex]") s1 = 1234, s2 = -1, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1235); + CHECK(i->operands.integer.slot_one == -1235); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -390,7 +390,7 @@ TEST_CASE_METHOD(EXFixture, "XOR", "[ex]") s1 = 1234, s2 = 5678, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 4860); + CHECK(i->operands.integer.slot_one == 4860); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -456,7 +456,7 @@ TEST_CASE_METHOD(EXFixture, "CMP less", "[ex]") i = execute_instr(s1, s2, s3, m); // should not be changed - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); CHECK(!ct->get_condition(EQ)); CHECK(!ct->get_condition(GT)); @@ -477,7 +477,7 @@ TEST_CASE_METHOD(EXFixture, "CMP equal", "[ex]") i = execute_instr(s1, s2, s3, m); // should not be changed - CHECK(i->get_s1() == 20); + CHECK(i->operands.integer.slot_one == 20); CHECK(ct->get_condition(EQ)); CHECK(!ct->get_condition(GT)); @@ -498,7 +498,7 @@ TEST_CASE_METHOD(EXFixture, "CMP greater", "[ex]") i = execute_instr(s1, s2, s3, m); // should not be changed - CHECK(i->get_s1() == 21); + CHECK(i->operands.integer.slot_one == 21); CHECK(!ct->get_condition(EQ)); CHECK(ct->get_condition(GT)); @@ -531,7 +531,7 @@ TEST_CASE_METHOD(EXFixture, "LOAD", "[ex]") s3 = -41958; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -553,7 +553,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI within bounds", "[ex]") s3 = -41958; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -570,7 +570,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI overflow", "[ex]") s1 = MAX_INT, s2 = 0, s3 = 1; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(i->operands.integer.slot_one == -(MAX_INT)-1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -587,7 +587,7 @@ TEST_CASE_METHOD(EXFixture, "ADDI underflow", "[ex]") s1 = -(MAX_INT)-1, s2 = 0, s3 = -1; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == MAX_INT); + CHECK(i->operands.integer.slot_one == MAX_INT); CHECK(!ct->get_condition(OF)); CHECK(ct->get_condition(UF)); @@ -604,7 +604,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI within bounds", "[ex]") s1 = 200, s2 = 0, s3 = 131; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); + CHECK(i->operands.integer.slot_one == 69); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -621,7 +621,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI overflow", "[ex]") s1 = -(MAX_INT)-1, s2 = 0, s3 = 1; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == MAX_INT); + CHECK(i->operands.integer.slot_one == MAX_INT); CHECK(!ct->get_condition(OF)); CHECK(ct->get_condition(UF)); @@ -638,7 +638,7 @@ TEST_CASE_METHOD(EXFixture, "SUBI underflow", "[ex]") s1 = MAX_INT, s2 = 0, s3 = -1; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -(MAX_INT)-1); + CHECK(i->operands.integer.slot_one == -(MAX_INT)-1); CHECK(ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -655,7 +655,7 @@ TEST_CASE_METHOD(EXFixture, "SFTRI within bounds", "[ex]") s1 = 1300, s2 = 0, s3 = 6; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 20); + CHECK(i->operands.integer.slot_one == 20); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -680,7 +680,7 @@ TEST_CASE_METHOD(EXFixture, "SFTLI within bounds", "[ex]") s1 = 13, s2 = 0, s3 = 6; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 832); + CHECK(i->operands.integer.slot_one == 832); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -705,7 +705,7 @@ TEST_CASE_METHOD(EXFixture, "ANDI", "[ex]") s1 = 1234, s2 = 0, s3 = 5678; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 1026); + CHECK(i->operands.integer.slot_one == 1026); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -722,7 +722,7 @@ TEST_CASE_METHOD(EXFixture, "ORI", "[ex]") s1 = 1234, s2 = 0, s3 = 5678; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 5886); + CHECK(i->operands.integer.slot_one == 5886); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -739,7 +739,7 @@ TEST_CASE_METHOD(EXFixture, "XORI", "[ex]") s1 = 1234, s2 = 0, s3 = 5678; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 4860); + CHECK(i->operands.integer.slot_one == 4860); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -756,7 +756,7 @@ TEST_CASE_METHOD(EXFixture, "STORE", "[ex]") s1 = 42000, s2 = 0, s3 = -41958; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -777,7 +777,7 @@ TEST_CASE_METHOD(EXFixture, "JMP", "[ex]") s1 = 42000, s2 = -41958, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -794,7 +794,7 @@ TEST_CASE_METHOD(EXFixture, "JRL", "[ex]") s1 = 100, s2 = 69, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); + CHECK(i->operands.integer.slot_one == 69); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -811,7 +811,7 @@ TEST_CASE_METHOD(EXFixture, "JAL", "[ex]") s1 = 42000, s2 = -41958, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 42); + CHECK(i->operands.integer.slot_one == 42); CHECK(!ct->get_condition(OF)); CHECK(!ct->get_condition(UF)); @@ -828,7 +828,7 @@ TEST_CASE_METHOD(EXFixture, "BEQ no cond", "[ex]") s1 = 100, s2 = 50, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); delete i; } @@ -844,7 +844,7 @@ TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]") this->ct->set_condition(EQ, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 50); + CHECK(i->operands.integer.slot_one == 50); delete i; } @@ -859,7 +859,7 @@ TEST_CASE_METHOD(EXFixture, "BGT no cond", "[ex]") s1 = 100, s2 = 50, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); delete i; } @@ -875,7 +875,7 @@ TEST_CASE_METHOD(EXFixture, "BGT", "[ex]") this->ct->set_condition(GT, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 50); + CHECK(i->operands.integer.slot_one == 50); delete i; } @@ -890,7 +890,7 @@ TEST_CASE_METHOD(EXFixture, "BUF no cond", "[ex]") s1 = 100, s2 = -42027, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); delete i; } @@ -906,7 +906,7 @@ TEST_CASE_METHOD(EXFixture, "BUF", "[ex]") this->ct->set_condition(UF, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 50); + CHECK(i->operands.integer.slot_one == 50); delete i; } @@ -921,7 +921,7 @@ TEST_CASE_METHOD(EXFixture, "BOF no cond", "[ex]") s1 = 100, s2 = -42027, s3 = 0; i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == -1); + CHECK(i->operands.integer.slot_one == -1); delete i; } @@ -937,7 +937,7 @@ TEST_CASE_METHOD(EXFixture, "BOF", "[ex]") this->ct->set_condition(OF, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 50); + CHECK(i->operands.integer.slot_one == 50); delete i; } diff --git a/tests/id.cc b/tests/id.cc index 321c013..e82adc3 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -26,7 +26,7 @@ class IDFixture InstrDTO *decode_bits(signed int raw) { InstrDTO *i = new InstrDTO(); - i->set_instr_bits(raw); + i->slot_A = raw; this->dum->set_curr_instr(i); i = this->ct->advance(WAIT); @@ -92,7 +92,7 @@ TEST_CASE_METHOD(IDFixture, "Parse invalid type", "[id]") t = this->encode_R_type(0b0, 0b1, 0b10, 0b11, 0b11); i = this->decode_bits(t); - CHECK(i->get_mnemonic() == NOP); + CHECK(i->mnemonic == NOP); delete i; } @@ -105,10 +105,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # one", "[id]") t = this->encode_R_type(0b101, 0b110, 0b111, 0b11, 0b0); i = this->decode_bits(t); - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == 0x00000000); - CHECK(i->get_s3() == 0x00000000); - CHECK(i->get_mnemonic() == MUL); + CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty + CHECK(i->operands.integer.slot_two == 0x00000000); + CHECK(i->operands.integer.slot_three == 0x00000000); + CHECK(i->mnemonic == MUL); delete i; } @@ -121,10 +121,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary r-type # two", "[id]") t = this->encode_R_type(0b10000, 0b01000, 0b00100, 0b10, 0b0); i = this->decode_bits(t); - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == 0x00000000); - CHECK(i->get_s3() == 0x00000000); - CHECK(i->get_mnemonic() == SUB); + CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty + CHECK(i->operands.integer.slot_two == 0x00000000); + CHECK(i->operands.integer.slot_three == 0x00000000); + CHECK(i->mnemonic == SUB); delete i; } @@ -137,10 +137,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # one", "[id]") t = this->encode_I_type(0xF, 0b101, 0b110, 0b0111, 0b1); i = this->decode_bits(t); - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == 0x00000000); - CHECK(i->get_s3() == 0xF); - CHECK(i->get_mnemonic() == ANDI); + CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty + CHECK(i->operands.integer.slot_two == 0x00000000); + CHECK(i->operands.integer.slot_three == 0xF); + CHECK(i->mnemonic == ANDI); delete i; } @@ -153,10 +153,10 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary i-type # two", "[id]") t = this->encode_I_type(0xCC, 0b101, 0b110, 0b1011, 0b1); i = this->decode_bits(t); - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == 0x00000000); - CHECK(i->get_s3() == 0xCC); - CHECK(i->get_mnemonic() == STOREV); + 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); delete i; } @@ -169,9 +169,9 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # one", "[id]") t = this->encode_J_type(0x3456, 0b10101, 0b0111, 0b10); i = this->decode_bits(t); - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == 0x3456); - CHECK(i->get_mnemonic() == BOF); + CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty + CHECK(i->operands.integer.slot_two == 0x3456); + CHECK(i->mnemonic == BOF); delete i; } @@ -185,9 +185,9 @@ TEST_CASE_METHOD(IDFixture, "Parse arbitrary j-type # two", "[id]") i = this->decode_bits(t); t = 0xFFFBBCCF; - CHECK(i->get_s1() == 0x00000000); // registers are empty - CHECK(i->get_s2() == t); - CHECK(i->get_mnemonic() == JAL); + CHECK(i->operands.integer.slot_one == 0x00000000); // registers are empty + CHECK(i->operands.integer.slot_two == t); + CHECK(i->mnemonic == JAL); delete i; } diff --git a/tests/if.cc b/tests/if.cc index 8b30d0e..59a7890 100644 --- a/tests/if.cc +++ b/tests/if.cc @@ -75,7 +75,7 @@ TEST_CASE_METHOD(IFFixture, "fetch returns single instuction", "[if_pipe]") InstrDTO *i; i = this->fetch_through(); - REQUIRE(i->get_instr_bits() == this->p[0]); + REQUIRE(i->slot_A == this->p[0]); delete i; } @@ -88,13 +88,13 @@ TEST_CASE_METHOD(IFFixture, "fetch returns two instuctions", "[if_pipe]") expected_cycles = this->m_delay + this->c_delay + 2; i = this->fetch_through(); - REQUIRE(i->get_instr_bits() == this->p[0]); + REQUIRE(i->slot_A == this->p[0]); delete i; expected_cycles += this->c_delay + 1; i = this->fetch_cache(); - REQUIRE(i->get_instr_bits() == this->p[1]); + REQUIRE(i->slot_A == this->p[1]); delete i; } @@ -124,7 +124,7 @@ TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", "[if_pipe]") i = this->ct->advance(WAIT); REQUIRE(i != nullptr); - REQUIRE(i->get_instr_bits() == this->p[0]); + REQUIRE(i->slot_A == this->p[0]); delete i; } -- cgit v1.2.3 From 263a5d86e0b1acde39523bdd9a49521752255c72 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 23:55:32 -0400 Subject: Remove 'type' field out of InstrDTO --- inc/id.h | 2 +- inc/instr.h | 2 -- inc/instrDTO.h | 5 ----- src/id.cc | 10 ++-------- src/if.cc | 1 - src/wb.cc | 21 ++++++++++++--------- 6 files changed, 15 insertions(+), 26 deletions(-) diff --git a/inc/id.h b/inc/id.h index dabf206..39485b6 100644 --- a/inc/id.h +++ b/inc/id.h @@ -78,7 +78,7 @@ class ID : public Stage * @param the resulting third field, which varies per type. * @param the resulting mnemonic. */ - void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t); + void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); void decode_R_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); void decode_I_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); void decode_J_type(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m); diff --git a/inc/instr.h b/inc/instr.h index 62af09a..85eae5b 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -62,8 +62,6 @@ enum Mnemonic { NOP, }; -enum Type { R, I, J, INV }; - namespace instr { // clang-format off diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 7775b20..6ab14b2 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -48,11 +48,6 @@ struct InstrDTO { * The mnemonic of the instruction. */ Mnemonic mnemonic; - // TODO delete me - /** - * Type of the instruction - */ - Type type; /** * The register this instruction checks out. */ diff --git a/src/id.cc b/src/id.cc index 14fe595..0135c21 100644 --- a/src/id.cc +++ b/src/id.cc @@ -66,44 +66,38 @@ void ID::advance_helper() { signed int s1, s2, s3; Mnemonic m; - Type t; if (curr_instr->mnemonic == NOP) this->status = OK; else { s1 = curr_instr->slot_A; - get_instr_fields(s1, s2, s3, m, t); + 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; - curr_instr->type = t; } } } void ID::get_instr_fields( - signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t) + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) { 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; } } diff --git a/src/if.cc b/src/if.cc index fd795c7..62a105c 100644 --- a/src/if.cc +++ b/src/if.cc @@ -59,7 +59,6 @@ void IF::advance_helper() this->curr_instr = new InstrDTO(); this->curr_instr->slot_A = bits; this->curr_instr->slot_B = this->pc; - this->curr_instr->type = INV; this->curr_instr->is_squashed = 0; this->curr_instr->checked_out = -1; this->curr_instr->mnemonic = ADD; diff --git a/src/wb.cc b/src/wb.cc index 08d512b..cd24c6a 100644 --- a/src/wb.cc +++ b/src/wb.cc @@ -19,13 +19,12 @@ #include "instrDTO.h" #include "response.h" #include "stage.h" -#include #include +#include void WB::advance_helper() { - if (this->curr_instr->mnemonic != NOP && - this->curr_instr->type != INV) { + if (this->curr_instr->mnemonic != NOP) { if (this->curr_instr->checked_out > 0) this->write_handler(); else if (this->should_jump()) @@ -46,30 +45,34 @@ void WB::write_handler() // POP performs a second register write reg = this->checked_out.front(); this->checked_out.pop_front(); - this->store_register(reg, this->curr_instr->operands.integer.slot_three); + this->store_register( + reg, this->curr_instr->operands.integer.slot_three); } this->checked_out.pop_front(); reg = this->curr_instr->checked_out; this->store_register(reg, this->curr_instr->operands.integer.slot_one); - } void WB::jump_handler() { if (this->curr_instr->operands.integer.slot_one > 0) { if (this->curr_instr->mnemonic == JAL) - this->gprs[1] = this->curr_instr->slot_B + 1;; + this->gprs[1] = this->curr_instr->slot_B + 1; + ; this->pc = this->curr_instr->operands.integer.slot_one; this->checked_out = {}; this->next->squash(); } } +// TODO clean this up... bool WB::should_jump() { - Type t; + vector Js = {JMP, JRL, JAL, BEQ, BGT, BUF, BOF, PUSH, POP, RET}; - t = this->curr_instr->type; - return t == J; + if (find(Js.begin(), Js.end(), this->curr_instr->mnemonic) != Js.end()) + return true; + else + return false; } -- cgit v1.2.3 From 7bbc7c7fea9bafc55754a1cf010f6553cce7d659 Mon Sep 17 00:00:00 2001 From: bd Date: Tue, 22 Apr 2025 23:59:15 -0400 Subject: Cleanup some imports --- inc/instr.h | 5 +---- inc/instrDTO.h | 3 --- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/inc/instr.h b/inc/instr.h index 85eae5b..98a1f0e 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -17,7 +17,6 @@ #ifndef INSTR_H #define INSTR_H -#include #include enum Mnemonic { @@ -64,9 +63,7 @@ enum Mnemonic { namespace instr { -// clang-format off - extern const std::unordered_map mnemonic_map; -// clang-format on +extern const std::unordered_map mnemonic_map; } // namespace instr #endif /* INSTR_H_INCLUDED */ diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 6ab14b2..1402526 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -18,9 +18,6 @@ #ifndef INSTRDTO_H #define INSTRDTO_H #include "instr.h" -#include -#include -#include struct U_INT_TYPE { signed int slot_one; -- cgit v1.2.3 From 051041c9cbe0752a50ac1a464df1c554b10cde0c Mon Sep 17 00:00:00 2001 From: bd Date: Wed, 23 Apr 2025 00:27:50 -0400 Subject: Move dum class to tests folder --- inc/dum.h | 40 ---------------------------------------- src/dum.cc | 38 -------------------------------------- tests/dum.h | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 78 deletions(-) delete mode 100644 inc/dum.h delete mode 100644 src/dum.cc create mode 100644 tests/dum.h diff --git a/inc/dum.h b/inc/dum.h deleted file mode 100644 index e5ec740..0000000 --- a/inc/dum.h +++ /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 . - -#ifndef DUM_H -#define DUM_H -#include "instrDTO.h" -#include "response.h" -#include "stage.h" - -/** - * Don't underestimate mocks (the DUM pipe stage). - */ -class DUM : public Stage -{ - public: - using Stage::Stage; - - InstrDTO *advance(Response p) override; - - void set_curr_instr(InstrDTO *); - - private: - void advance_helper() override; -}; - -#endif /* DUM_H_INCLUDED */ diff --git a/src/dum.cc b/src/dum.cc deleted file mode 100644 index fd3b7a6..0000000 --- a/src/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/tests/dum.h b/tests/dum.h new file mode 100644 index 0000000..5bfc646 --- /dev/null +++ b/tests/dum.h @@ -0,0 +1,35 @@ +#ifndef DUM_H +#define DUM_H + +#include "instrDTO.h" +#include "response.h" +#include "stage.h" + +/** + * Don't underestimate mocks (the DUM pipe stage). + */ +class DUM : public Stage +{ + public: + using Stage::Stage; + + InstrDTO *advance(Response p) override + { + 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 set_curr_instr(InstrDTO *d) { this->curr_instr = d; }; + + private: + void advance_helper() override{}; +}; + +#endif /* DUM_H_INCLUDED */ -- cgit v1.2.3 From 8e33ba4499bced747f66ed436211876d220342d6 Mon Sep 17 00:00:00 2001 From: bd Date: Wed, 23 Apr 2025 00:47:24 -0400 Subject: Rename Response.WAIT to READY, delete BLOCKED --- inc/response.h | 3 +-- inc/stage.h | 2 +- src/controller.cc | 2 +- src/if.cc | 2 +- src/response.cc | 2 +- src/stage.cc | 8 ++++---- tests/controller.cc | 2 +- tests/dum.h | 2 +- tests/ex.cc | 4 ++-- tests/id.cc | 4 ++-- tests/if.cc | 8 ++++---- 11 files changed, 19 insertions(+), 20 deletions(-) diff --git a/inc/response.h b/inc/response.h index 501923a..c1f38e7 100644 --- a/inc/response.h +++ b/inc/response.h @@ -21,8 +21,7 @@ enum Response { OK, - WAIT, - BLOCKED, + READY, STALLED, }; diff --git a/inc/stage.h b/inc/stage.h index 745e0ff..7dcb7b4 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -50,7 +50,7 @@ class Stage * ready to accept a new instruction object next cycle. * @return a DTO object containing the next instruction to be processed. * - * Must set the status to WAIT when the current instruction is evicted.. + * Must set the status to READY when the current instruction is evicted.. */ virtual InstrDTO *advance(Response p); diff --git a/src/controller.cc b/src/controller.cc index 1c379ec..8df4b97 100644 --- a/src/controller.cc +++ b/src/controller.cc @@ -38,7 +38,7 @@ void Controller::run_for(int number) int i; for (i = 0; i < number; ++i) { try { - this->advance(WAIT); + this->advance(READY); } catch (HaltException &e) { break; } diff --git a/src/if.cc b/src/if.cc index 62a105c..5f07ee2 100644 --- a/src/if.cc +++ b/src/if.cc @@ -25,7 +25,7 @@ InstrDTO *IF::advance(Response p) InstrDTO *r = nullptr; this->advance_helper(); - if (this->curr_instr != nullptr && p == WAIT) { + if (this->curr_instr != nullptr && p == READY) { // don't increment PC if the PC was just set by wb if (this->curr_instr->is_squashed != 1) ++this->pc; diff --git a/src/response.cc b/src/response.cc index d56419a..7624b82 100644 --- a/src/response.cc +++ b/src/response.cc @@ -20,6 +20,6 @@ std::ostream &operator<<(std::ostream &os, Response r) { - const std::string nameR[] = {"OK", "WAIT", "BLOCKED", "STALLED"}; + const std::string nameR[] = {"OK", "READY", "STALLED"}; return os << nameR[r]; } diff --git a/src/stage.cc b/src/stage.cc index e5a4333..55756b6 100644 --- a/src/stage.cc +++ b/src/stage.cc @@ -23,7 +23,7 @@ Stage::Stage(Stage *next) { this->next = next; this->curr_instr = nullptr; - this->status = WAIT; + this->status = READY; } Stage::~Stage() { delete this->next; }; @@ -50,15 +50,15 @@ InstrDTO *Stage::advance(Response p) if (this->curr_instr && this->status != OK) { this->advance_helper(); } - if (this->status == OK && p == WAIT && this->curr_instr) { + if (this->status == OK && p == READY && this->curr_instr) { // mutual consent r = new InstrDTO(*this->curr_instr); delete curr_instr; curr_instr = nullptr; - this->status = WAIT; + this->status = READY; } - n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; + n = (p != READY || this->status != READY) ? STALLED : READY; s = this->next->advance(n); if (s) this->curr_instr = s; diff --git a/tests/controller.cc b/tests/controller.cc index 1d1ddb6..9bc71f6 100644 --- a/tests/controller.cc +++ b/tests/controller.cc @@ -37,7 +37,7 @@ class ControllerPipeFixture InstrDTO *i = nullptr; int j; for (j = 0; j < this->stage_num + 1; ++j) { - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i == nullptr); } } diff --git a/tests/dum.h b/tests/dum.h index 5bfc646..e60ffad 100644 --- a/tests/dum.h +++ b/tests/dum.h @@ -17,7 +17,7 @@ class DUM : public Stage { InstrDTO *r = nullptr; - if (this->curr_instr && p == WAIT) { + if (this->curr_instr && p == READY) { r = new InstrDTO(*this->curr_instr); delete this->curr_instr; curr_instr = nullptr; diff --git a/tests/ex.cc b/tests/ex.cc index 1fc333e..5972182 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -33,9 +33,9 @@ class EXFixture i->mnemonic = m; this->dum->set_curr_instr(i); - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i == nullptr); - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i != nullptr); return i; diff --git a/tests/id.cc b/tests/id.cc index e82adc3..a81e967 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -29,9 +29,9 @@ class IDFixture i->slot_A = raw; this->dum->set_curr_instr(i); - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i == nullptr); - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i != nullptr); return i; diff --git a/tests/if.cc b/tests/if.cc index 59a7890..e2a7dbe 100644 --- a/tests/if.cc +++ b/tests/if.cc @@ -36,7 +36,7 @@ class IFFixture int i; for (i = 0; i < this->m_delay + 1; ++i) { - r = this->ct->advance(WAIT); + r = this->ct->advance(READY); // check response CHECK(r == nullptr); } @@ -52,11 +52,11 @@ class IFFixture int i; for (i = 0; i < this->c_delay; ++i) { - r = this->ct->advance(WAIT); + r = this->ct->advance(READY); // check response REQUIRE(r == nullptr); } - r = this->ct->advance(WAIT); + r = this->ct->advance(READY); // check response REQUIRE(r != nullptr); return r; @@ -122,7 +122,7 @@ TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", "[if_pipe]") REQUIRE(i != nullptr); } - i = this->ct->advance(WAIT); + i = this->ct->advance(READY); REQUIRE(i != nullptr); REQUIRE(i->slot_A == this->p[0]); -- cgit v1.2.3 From 9ef2928aefd0983c7b3b04023c0b958b86dd77ff Mon Sep 17 00:00:00 2001 From: bd Date: Thu, 24 Apr 2025 19:33:06 -0400 Subject: Fix presumed bug with illegal types --- src/id.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/id.cc b/src/id.cc index 0135c21..d8368c8 100644 --- a/src/id.cc +++ b/src/id.cc @@ -98,6 +98,7 @@ void ID::get_instr_fields( this->decode_J_type(s1, s2, s3, m); break; case 0b11: + m = NOP; this->status = OK; } } -- cgit v1.2.3 From a3528b83dd10fa9cdf7ef5635f615c1b295f3f4c Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 25 Apr 2025 21:12:58 -0400 Subject: Pass full DTO to GUI --- gui/gui.cc | 59 +++++++++++++++++++++++++++++------------------------------ gui/gui.h | 10 +++++----- gui/worker.cc | 10 +++++----- gui/worker.h | 10 +++++----- inc/id.h | 2 -- inc/if.h | 2 -- inc/stage.h | 15 ++++++++------- src/id.cc | 10 ---------- src/if.cc | 9 --------- src/stage.cc | 13 +------------ 10 files changed, 53 insertions(+), 87 deletions(-) diff --git a/gui/gui.cc b/gui/gui.cc index 496a443..bf9e6cf 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -169,36 +169,36 @@ void GUI::on_worker_refresh_gui(int cycles, int pc) ui->cycle_counter->set_value(cycles); } -void GUI::onWorkerFetchInfo(const std::vector info) +void GUI::onWorkerFetchInfo(const InstrDTO *i) { - if (!info.empty()) { - ui->fetch_squashed->setText(QString::number(info[0])); - ui->fetch_bits->set_value(info[1]); + if (i) { + ui->fetch_squashed->setText(QString::number(i->is_squashed)); + ui->fetch_bits->set_value(i->slot_A); } else { ui->fetch_squashed->clear(); ui->fetch_bits->clear(); } } -void GUI::onWorkerDecodeInfo(const std::vector info) +void GUI::onWorkerDecodeInfo(const InstrDTO *i) { - if (!info.empty()) { - ui->decode_squashed->setText(QString::number(info[0])); - ui->decode_bits->set_value(info[1]); + if (i) { + ui->decode_squashed->setText(QString::number(i->is_squashed)); + ui->decode_bits->set_value(i->slot_A); } else { ui->decode_squashed->clear(); ui->decode_bits->clear(); } } -void GUI::onWorkerExecuteInfo(const std::vector info) +void GUI::onWorkerExecuteInfo(const InstrDTO *i) { - if (!info.empty()) { - ui->execute_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); - ui->execute_squashed->setText(QString::number(info[1])); - ui->execute_s1->set_value(info[2]); - ui->execute_s2->set_value(info[3]); - ui->execute_s3->set_value(info[4]); + if (i) { + ui->execute_mnemonic->setText(mnemonicToString(i->mnemonic)); + ui->execute_squashed->setText(QString::number(i->is_squashed)); + ui->execute_s1->set_value(i->operands.integer.slot_one); + ui->execute_s2->set_value(i->operands.integer.slot_two); + ui->execute_s3->set_value(i->operands.integer.slot_three); } else { ui->execute_mnemonic->clear(); ui->execute_squashed->clear(); @@ -208,15 +208,14 @@ void GUI::onWorkerExecuteInfo(const std::vector info) } } -void GUI::onWorkerMemoryInfo(const std::vector info) +void GUI::onWorkerMemoryInfo(const InstrDTO *i) { - if (!info.empty()) { - std::cout << "this " << info[3] << std::endl; - ui->memory_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); - ui->memory_squashed->setText(QString::number(info[1])); - ui->memory_s1->set_value(info[2]); - ui->memory_s2->set_value(info[3]); - ui->memory_s3->set_value(info[4]); + if (i) { + ui->memory_mnemonic->setText(mnemonicToString(i->mnemonic)); + ui->memory_squashed->setText(QString::number(i->is_squashed)); + ui->memory_s1->set_value(i->operands.integer.slot_one); + ui->memory_s2->set_value(i->operands.integer.slot_two); + ui->memory_s3->set_value(i->operands.integer.slot_three); } else { ui->memory_mnemonic->clear(); ui->memory_squashed->clear(); @@ -226,14 +225,14 @@ void GUI::onWorkerMemoryInfo(const std::vector info) } } -void GUI::onWorkerWriteBackInfo(const std::vector info) +void GUI::onWorkerWriteBackInfo(const InstrDTO *i) { - if (!info.empty()) { - ui->write_mnemonic->setText(mnemonicToString((Mnemonic)info[0])); - ui->write_squashed->setText(QString::number(info[1])); - ui->write_s1->set_value(info[2]); - ui->write_s2->set_value(info[3]); - ui->write_s3->set_value(info[4]); + if (i) { + ui->write_mnemonic->setText(mnemonicToString(i->mnemonic)); + ui->write_squashed->setText(QString::number(i->is_squashed)); + ui->write_s1->set_value(i->operands.integer.slot_one); + ui->write_s2->set_value(i->operands.integer.slot_two); + ui->write_s3->set_value(i->operands.integer.slot_three); } else { ui->write_mnemonic->clear(); ui->write_squashed->clear(); diff --git a/gui/gui.h b/gui/gui.h index 7b03f75..b3a3110 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -57,15 +57,15 @@ class GUI : public QMainWindow private slots: void on_worker_refresh_gui(int value, int pc); - void onWorkerFetchInfo(const std::vector info); + void onWorkerFetchInfo(const InstrDTO *); - void onWorkerDecodeInfo(const std::vector info); + void onWorkerDecodeInfo(const InstrDTO *); - void onWorkerExecuteInfo(const std::vector info); + void onWorkerExecuteInfo(const InstrDTO *); - void onWorkerMemoryInfo(const std::vector info); + void onWorkerMemoryInfo(const InstrDTO *); - void onWorkerWriteBackInfo(const std::vector info); + void onWorkerWriteBackInfo(const InstrDTO *); void onWorkerShowStorage( const std::vector> data, int i); diff --git a/gui/worker.cc b/gui/worker.cc index 2652fce..203f907 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -89,10 +89,10 @@ void Worker::runSteps(int steps) emit storage(this->s.at(i - 1)->view(0, 1 << this->size_inc * i), i + 1); emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); - emit if_info(this->if_stage->stage_info()); - emit id_info(this->id_stage->stage_info()); - emit ex_info(this->ex_stage->stage_info()); - emit mm_info(this->mm_stage->stage_info()); - emit wb_info(this->wb_stage->stage_info()); + emit if_info(this->if_stage->get_instr()); + emit id_info(this->id_stage->get_instr()); + emit ex_info(this->ex_stage->get_instr()); + emit mm_info(this->mm_stage->get_instr()); + emit wb_info(this->wb_stage->get_instr()); this->ct_mutex.unlock(); } diff --git a/gui/worker.h b/gui/worker.h index 95c81d5..072263a 100644 --- a/gui/worker.h +++ b/gui/worker.h @@ -72,11 +72,11 @@ class Worker : public QObject void storage(const std::vector> data, int i); void register_storage(const std::array data); - void if_info(const std::vector info); - void id_info(const std::vector info); - void ex_info(const std::vector info); - void mm_info(const std::vector info); - void wb_info(const std::vector info); + void if_info(const InstrDTO *); + void id_info(const InstrDTO *); + void ex_info(const InstrDTO *); + void mm_info(const InstrDTO *); + void wb_info(const InstrDTO *); void finished(); }; diff --git a/inc/id.h b/inc/id.h index 39485b6..aafe2e5 100644 --- a/inc/id.h +++ b/inc/id.h @@ -50,8 +50,6 @@ class ID : public Stage */ void write_guard(signed int &r); - std::vector stage_info() override; - private: /** * Helper for `get_instr_fields` diff --git a/inc/if.h b/inc/if.h index c374145..f0eb6e2 100644 --- a/inc/if.h +++ b/inc/if.h @@ -28,8 +28,6 @@ class IF : public Stage InstrDTO *advance(Response p) override; - std::vector stage_info() override; - private: void advance_helper() override; }; diff --git a/inc/stage.h b/inc/stage.h index 7dcb7b4..16f1235 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -53,8 +53,14 @@ class Stage * Must set the status to READY when the current instruction is evicted.. */ virtual InstrDTO *advance(Response p); - - virtual std::vector stage_info(); + /** + * @return the current instruction. + */ + InstrDTO *get_instr(); + /** + * Squashes the pipeline. + */ + void squash(); /* The following methods are made public so that they may be tested, and are * not to be called from outside classes during standard execution. @@ -72,11 +78,6 @@ class Stage */ void set_condition(CC c, bool v); - /** - * Squashes the pipeline. - */ - void squash(); - /** * The set of registers currently checked out. */ diff --git a/src/id.cc b/src/id.cc index d8368c8..d2a8f02 100644 --- a/src/id.cc +++ b/src/id.cc @@ -211,13 +211,3 @@ void ID::decode_J_type( } } - -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->slot_A); - } - return info; -} diff --git a/src/if.cc b/src/if.cc index 5f07ee2..0f622d4 100644 --- a/src/if.cc +++ b/src/if.cc @@ -37,15 +37,6 @@ InstrDTO *IF::advance(Response p) 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->slot_A); - } - return info; -} - void IF::advance_helper() { Response r; diff --git a/src/stage.cc b/src/stage.cc index 55756b6..4efe2fe 100644 --- a/src/stage.cc +++ b/src/stage.cc @@ -65,18 +65,7 @@ InstrDTO *Stage::advance(Response p) return r; } -std::vector Stage::stage_info() -{ - std::vector info; - if (this->curr_instr) { - info.push_back(this->curr_instr->mnemonic); - info.push_back(this->curr_instr->is_squashed); - info.push_back(this->curr_instr->operands.integer.slot_one); - info.push_back(this->curr_instr->operands.integer.slot_two); - info.push_back(this->curr_instr->operands.integer.slot_three); - } - return info; -} +InstrDTO *Stage::get_instr() { return this->curr_instr; } void Stage::set_condition(CC c, bool v) { -- cgit v1.2.3 From f3e6d5ed8acdeb3f5eccffb5aeeab2e7b040908c Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 25 Apr 2025 21:19:10 -0400 Subject: Separate update method for worker into its own method --- gui/worker.cc | 16 ++++++++++------ gui/worker.h | 7 +++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/gui/worker.cc b/gui/worker.cc index 203f907..22f8738 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -69,24 +69,28 @@ void Worker::configure( delete old; this->ct_mutex.unlock(); - emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); + this->update(); } void Worker::runSteps(int steps) { - unsigned long i; - - this->ct_mutex.lock(); qDebug() << "Running for " << steps << "steps"; this->ct->run_for(steps); + this->update(); +} - // TODO move these to separate functions +void Worker::update() +{ + unsigned long i; + + this->ct_mutex.lock(); emit register_storage(this->ct->get_gprs()); emit storage(this->s.at(0)->view(0, 255), 1); for (i = 1; i < s.size(); ++i) - emit storage(this->s.at(i - 1)->view(0, 1 << this->size_inc * i), i + 1); + emit storage( + this->s.at(i - 1)->view(0, 1 << this->size_inc * i), i + 1); emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); emit if_info(this->if_stage->get_instr()); diff --git a/gui/worker.h b/gui/worker.h index 072263a..06e4a16 100644 --- a/gui/worker.h +++ b/gui/worker.h @@ -78,6 +78,13 @@ class Worker : public QObject void mm_info(const InstrDTO *); void wb_info(const InstrDTO *); void finished(); + + private: + /** + * Sets the GUI signals to update the storage, clock cycle, and stage + * displays. + */ + void update(); }; #endif // WORKER_H -- cgit v1.2.3 From 55a5a757dea26efad1e57fa7805c62ed19206ad3 Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 25 Apr 2025 21:23:02 -0400 Subject: Remove onWorkerFinished --- gui/gui.cc | 6 ------ gui/gui.h | 2 -- gui/worker.cc | 3 --- 3 files changed, 11 deletions(-) diff --git a/gui/gui.cc b/gui/gui.cc index bf9e6cf..905b018 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -92,7 +92,6 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI) }); // Proper cleanup when worker finishes - connect(worker, &Worker::finished, this, &GUI::onWorkerFinished); connect(worker, &Worker::finished, &workerThread, &QThread::quit); connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); @@ -254,12 +253,8 @@ void GUI::onWorkerShowRegisters(const std::array &data) displayArrayHTML(this->tab_text_boxes.at(0), data); } -void GUI::onWorkerFinished() { qDebug() << "Worker has finished processing."; } - void GUI::on_upload_intructions_btn_clicked() { - qDebug() << "Upload intructions button clicked."; - // why ui->register_table, or now ui->storage QString filePath = QFileDialog::getOpenFileName( ui->storage, "Open Binary File", QDir::homePath(), @@ -311,7 +306,6 @@ void GUI::on_base_toggle_checkbox_checkStateChanged(const Qt::CheckState &state) void GUI::on_step_btn_clicked() { - qDebug() << "Run step button clicked."; // try to configure first if (!this->ready) this->on_config_clicked(); diff --git a/gui/gui.h b/gui/gui.h index b3a3110..26e9b03 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -72,8 +72,6 @@ class GUI : public QMainWindow void onWorkerShowRegisters(const std::array &data); - void onWorkerFinished(); - void on_upload_intructions_btn_clicked(); void on_upload_program_state_btn_clicked(); diff --git a/gui/worker.cc b/gui/worker.cc index 22f8738..a0e21f6 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -23,8 +23,6 @@ Worker::Worker(QObject *parent) : QObject(parent) {} Worker::~Worker() { emit finished(); - qDebug() << "Worker destructor called in thread:" - << QThread::currentThread(); delete this->ct; } @@ -74,7 +72,6 @@ void Worker::configure( void Worker::runSteps(int steps) { - qDebug() << "Running for " << steps << "steps"; this->ct->run_for(steps); this->update(); } -- cgit v1.2.3 From 858a682d11cef5b7695050967b1c6b184eda3c6a Mon Sep 17 00:00:00 2001 From: bd Date: Fri, 25 Apr 2025 23:05:00 -0400 Subject: Add DigitLabelHelper, which centralizes integer display formatting --- gui/digitlabel.cc | 10 +++------- gui/digitlabelhelper.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) create mode 100644 gui/digitlabelhelper.h diff --git a/gui/digitlabel.cc b/gui/digitlabel.cc index 8314943..a24a1e1 100644 --- a/gui/digitlabel.cc +++ b/gui/digitlabel.cc @@ -16,6 +16,7 @@ // along with this program. If not, see . #include "digitlabel.h" +#include "digitlabelhelper.h" #include "gui.h" DigitLabel::DigitLabel(QWidget *parent) : QLabel(parent) { setText(QString()); } @@ -42,11 +43,6 @@ void DigitLabel::on_hex_toggle(bool is_hex) void DigitLabel::update_display() { QString t; - if (this->is_cleared) { - setText(QString()); - } else { - t = (this->is_hex) ? QString::number(this->v, 16).toUpper() - : QString::number(this->v); - setText(t); - } + t = DigitLabelHelper::format_value(this->v, this->is_hex, this->is_cleared); + setText(t); } diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h new file mode 100644 index 0000000..a0f845f --- /dev/null +++ b/gui/digitlabelhelper.h @@ -0,0 +1,43 @@ +// 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 . + +#ifndef DIGITLABELHELPER_H +#define DIGITLABELHELPER_H + +#include + +class DigitLabelHelper +{ + public: + /** + * Contains the main formatting logic used to format integers. + * @param the value to be formated + * @param if the value should be displayed in hex. If false, displays in + * decimal. + * @param if the value should display. + * @return a string respecting the above parameters. + */ + static QString format_value(int value, bool is_hex, bool is_cleared = false) + { + if (is_cleared) + return QString(); + return is_hex ? QString::number(value, 16).toUpper() + : QString::number(value); + } +}; + +#endif // DIGITLABELHELPER_H -- cgit v1.2.3 From c98a0c26c4ccb5c4ae0e9f5810be910a7b299037 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 03:06:14 -0400 Subject: Add proper tables display for storage devices --- gui/gui.cc | 71 ++++++++++++++------------------------- gui/gui.h | 6 ++-- gui/resources/styles.qss | 30 ++++++++++++----- gui/storageview.cc | 70 +++++++++++++++++++++++++++++++++++++++ gui/storageview.h | 86 ++++++++++++++++++++++++++++++++++++++++++++++++ gui/worker.cc | 20 +++++++++-- gui/worker.h | 9 ++++- 7 files changed, 229 insertions(+), 63 deletions(-) create mode 100644 gui/storageview.cc create mode 100644 gui/storageview.h diff --git a/gui/gui.cc b/gui/gui.cc index 905b018..9baed38 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -19,8 +19,11 @@ #include "./ui_gui.h" #include "dynamicwaysentry.h" #include "messages.h" +#include "storageview.h" #include #include +#include +#include GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI) { @@ -131,37 +134,6 @@ void displayArrayHTML(QTextEdit *textEdit, const std::array &data) textEdit->setReadOnly(true); } -void displayTableHTML( - QTextEdit *textEdit, - const std::vector> &data) -{ - textEdit->setReadOnly(false); - QString tableText = ""; - - int index = 0; - for (const auto &row : data) { - tableText += ""; - for (signed int value : row) { - tableText += QString("") - .arg(QString::asprintf("%04X", value)) - .arg(index); - index++; - } - tableText += ""; - } - - tableText += "
" - "%1 %2" - "
"; - - textEdit->setHtml(tableText); - textEdit->setReadOnly(true); -} - void GUI::on_worker_refresh_gui(int cycles, int pc) { ui->p_counter->set_value(pc); @@ -241,16 +213,15 @@ void GUI::onWorkerWriteBackInfo(const InstrDTO *i) } } -void GUI::onWorkerShowStorage( - const std::vector> data, int i) +void GUI::onWorkerShowStorage(const QVector> &data, int i) { - std::cout << this->tab_text_boxes.size() << std::endl; - displayTableHTML(this->tab_text_boxes.at(i), data); + this->tab_boxes.at(i)->set_data(data); } void GUI::onWorkerShowRegisters(const std::array &data) { - displayArrayHTML(this->tab_text_boxes.at(0), data); + ; + // displayArrayHTML(this->tab_boxes.at(0), data); } void GUI::on_upload_intructions_btn_clicked() @@ -368,27 +339,33 @@ void GUI::on_config_clicked() void GUI::make_tabs(int num) { int i; - QStringList names; - QTextEdit *e; + QStringList xTra; + StorageView *e; + QTableView *t; QString n; - names = {"Registers", "DRAM"}; + xTra = {"Registers", "DRAM"}; ui->storage->clear(); - this->tab_text_boxes.clear(); + + this->tab_boxes.clear(); + qDeleteAll(this->tab_boxes); for (i = 0; i < num; ++i) { - e = new QTextEdit(); - e->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + e = new StorageView(10, this); + + t = new QTableView; + t->setModel(e); + t->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // make the name - if (i < names.size()) - n = names[i]; + if (i < xTra.size()) + n = xTra[i]; else - n = QString("Level %1").arg(i - 1); + n = QString("L%1").arg(i - 1); - ui->storage->addTab(e, n); - this->tab_text_boxes.push_back(e); + ui->storage->addTab(t, n); + this->tab_boxes.push_back(e); } } diff --git a/gui/gui.h b/gui/gui.h index 26e9b03..f723729 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -18,6 +18,7 @@ #ifndef GUI_H #define GUI_H +#include "storageview.h" #include "worker.h" #include #include @@ -67,8 +68,7 @@ class GUI : public QMainWindow void onWorkerWriteBackInfo(const InstrDTO *); - void onWorkerShowStorage( - const std::vector> data, int i); + void onWorkerShowStorage(const QVector> &data, int i); void onWorkerShowRegisters(const std::array &data); @@ -104,7 +104,7 @@ class GUI : public QMainWindow /** * The list of storage displays. */ - std::vector tab_text_boxes; + std::vector tab_boxes; /** * Whether or not numerical values are currently displaying in hex. diff --git a/gui/resources/styles.qss b/gui/resources/styles.qss index 76d0311..a61035e 100644 --- a/gui/resources/styles.qss +++ b/gui/resources/styles.qss @@ -50,15 +50,27 @@ QGroupBox::title { QLabel { } -/* text entry */ -QLineEdit { - font-size: 18pt; - border-radius: 0px; - padding: 0 4px; - selection-background-color: "#00cc00"; +QTableView { + border: 0px; + selection-background-color: transparent; + selection-color: black; + outline: none; +} + +QTableView::item { + border: none; + padding: 4px; +} + +QHeaderView::section { + color: "#00cc00"; + background-color: "#000200"; + border: none; } -QTextEdit, QListView { +QTableView QTableCornerButton::section { + background-color: "#000200"; + border: none; } QPushButton { @@ -71,8 +83,8 @@ QPushButton { QPushButton:pressed { color: "#00cc00"; - background-color: "#000200"; -} + background-color: "#000200";} + QPushButton:flat { border: none; /* no border for a flat push button */ diff --git a/gui/storageview.cc b/gui/storageview.cc new file mode 100644 index 0000000..f6f9736 --- /dev/null +++ b/gui/storageview.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 "storageview.h" +#include "definitions.h" +#include +#include + +StorageView::StorageView(int rows, QObject *parent) + : QAbstractTableModel(parent) +{ + this->r = rows; + this->d.resize(rows); + for (auto &row : this->d) + row.resize(LINE_SIZE, 0); +} + +int StorageView::rowCount(const QModelIndex &) const { return this->r; } + +int StorageView::columnCount(const QModelIndex &) const { return LINE_SIZE; } + +QVariant StorageView::data(const QModelIndex &i, int role) const +{ + Qt::Alignment a; + + if (role == Qt::TextAlignmentRole) { + a = Qt::AlignRight | Qt::AlignVCenter; + return QVariant(static_cast(a)); + } + if (!i.isValid() || role != Qt::DisplayRole) + return QVariant(); + return this->d[i.row()][i.column()]; +} + +QVariant StorageView::headerData(int section, Qt::Orientation o, int role) const +{ + if (role != Qt::DisplayRole) + return QVariant(); + + if (o == Qt::Vertical) { + return section * 4; + } + return QVariant(); +} + +Qt::ItemFlags StorageView::flags(const QModelIndex &i) const { + (void)i; + return Qt::ItemIsEnabled; +} + +void StorageView::set_data(const QVector> &data) +{ + beginResetModel(); + this->d = data; + endResetModel(); +} diff --git a/gui/storageview.h b/gui/storageview.h new file mode 100644 index 0000000..4956f23 --- /dev/null +++ b/gui/storageview.h @@ -0,0 +1,86 @@ +// 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 . + +#ifndef STORAGEVIEW_H +#define STORAGEVIEW_H + +#include +#include + +// see https://doc.qt.io/qt-6/qabstracttablemodel.html +class StorageView : public QAbstractTableModel +{ + Q_OBJECT + public: + /** + * Constructor. Initializes a clean StorageView object with + * `rows' rows. + * @param the number of rows + */ + StorageView(int rows, QObject *parent = nullptr); + + /** + * Returns the number of rows in this table. + * @param the parent + * @return the number of rows under the given parent. + */ + int rowCount(const QModelIndex &) const override; + /** + * Returns the number of columns in this table. + * @param the parent + * @return the number of columns under the given parent (hint: it's + * LINE_SIZE) + */ + int columnCount(const QModelIndex &) const override; + + /** + * Returns a properly formatted cell, including alignment.This function is + * specific to the implementation details of QAbstractTableModel. + */ + QVariant + data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + + /** + * Adds custom formatting options for row and column headers. + */ + QVariant headerData( + int section, + Qt::Orientation o, + int role = Qt::DisplayRole) const override; + + /** + * Ensures the table is enabled, but not selectable. + */ + Qt::ItemFlags flags(const QModelIndex &i) const override; + + /** + * @param field to assign to `this->d' + */ + void set_data(const QVector> &data); + + private: + /** + * The number of rows in this table. + */ + int r; + /** + * The data this table displays. + */ + QVector> d; +}; + +#endif // STORAGEVIEW_H diff --git a/gui/worker.cc b/gui/worker.cc index a0e21f6..6419b73 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -83,11 +83,10 @@ void Worker::update() this->ct_mutex.lock(); emit register_storage(this->ct->get_gprs()); - emit storage(this->s.at(0)->view(0, 255), 1); + emit storage(this->data_to_QT(this->s.at(0)->get_data()), 1); for (i = 1; i < s.size(); ++i) - emit storage( - this->s.at(i - 1)->view(0, 1 << this->size_inc * i), i + 1); + emit storage(this->data_to_QT(this->s.at(i - 1)->get_data()), i + 1); emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); emit if_info(this->if_stage->get_instr()); @@ -97,3 +96,18 @@ void Worker::update() emit wb_info(this->wb_stage->get_instr()); this->ct_mutex.unlock(); } + +QVector> +Worker::data_to_QT(std::vector> data) +{ + QVector> r; + QVector tmp; + + r.reserve(static_cast(data.size())); + + for (const auto &line : data) { + tmp = QVector(line.begin(), line.end()); + r.append(tmp); + } + return r; +} diff --git a/gui/worker.h b/gui/worker.h index 06e4a16..c0e72d3 100644 --- a/gui/worker.h +++ b/gui/worker.h @@ -70,7 +70,7 @@ class Worker : public QObject signals: void clock_cycles(int value, int pc); void - storage(const std::vector> data, int i); + storage(QVector> data, int i); void register_storage(const std::array data); void if_info(const InstrDTO *); void id_info(const InstrDTO *); @@ -80,6 +80,13 @@ class Worker : public QObject void finished(); private: + /** + * Converts a vector of arrays into a QVector of QVectors. + * @param the original data + * @return a less universal version of the same thing + */ + QVector> + data_to_QT(std::vector> data); /** * Sets the GUI signals to update the storage, clock cycle, and stage * displays. -- cgit v1.2.3 From a78163745b43a0c420ae4ea5792def30a94420eb Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 03:39:28 -0400 Subject: Partial cache size generation, full cache display --- gui/gui.cc | 26 +++++++++++++++----------- gui/gui.h | 5 +++++ gui/util.cc | 16 ++++++++++++++++ gui/util.h | 8 ++++++++ gui/worker.cc | 8 +++----- gui/worker.h | 5 ----- 6 files changed, 47 insertions(+), 21 deletions(-) create mode 100644 gui/util.cc create mode 100644 gui/util.h diff --git a/gui/gui.cc b/gui/gui.cc index 9baed38..ecdf9d3 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -20,10 +20,11 @@ #include "dynamicwaysentry.h" #include "messages.h" #include "storageview.h" +#include "util.h" +#include #include #include #include -#include GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI) { @@ -332,6 +333,8 @@ void GUI::on_config_clicked() else this->set_status(get_initialize, "happy"); + this->curr_cache_levels = ways.size(); + emit sendConfigure(ways, this->p, is_pipelined); make_tabs(2 + ways.size()); } @@ -339,31 +342,32 @@ void GUI::on_config_clicked() void GUI::make_tabs(int num) { int i; - QStringList xTra; StorageView *e; QTableView *t; QString n; - xTra = {"Registers", "DRAM"}; - ui->storage->clear(); this->tab_boxes.clear(); qDeleteAll(this->tab_boxes); for (i = 0; i < num; ++i) { - e = new StorageView(10, this); + // make the name + if (i == 0) { + n = "Registers"; + e = new StorageView(0, this); + } else if (i == 1) { + n = "DRAM"; + e = new StorageView(MEM_LINES, this); + } else { + n = QString("L%1").arg(i - 1); + e = new StorageView(cache_size_mapper(this->curr_cache_levels, i), this); + } t = new QTableView; t->setModel(e); t->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); - // make the name - if (i < xTra.size()) - n = xTra[i]; - else - n = QString("L%1").arg(i - 1); - ui->storage->addTab(t, n); this->tab_boxes.push_back(e); } diff --git a/gui/gui.h b/gui/gui.h index f723729..10c8f67 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -101,6 +101,11 @@ class GUI : public QMainWindow */ bool ready; + /** + * The current number of cache levels. + */ + int curr_cache_levels; + /** * The list of storage displays. */ diff --git a/gui/util.cc b/gui/util.cc new file mode 100644 index 0000000..ee75e56 --- /dev/null +++ b/gui/util.cc @@ -0,0 +1,16 @@ +#include "util.h" + +int cache_size_mapper(int total_levels, int level) +{ + const int y_min = 4; + const int y_max = 12; + double f, r; + + if (total_levels <= 1) + return 8; + + f = level / total_levels; + r = y_min + f * (y_max - y_min); + + return r; +} diff --git a/gui/util.h b/gui/util.h new file mode 100644 index 0000000..87c33f6 --- /dev/null +++ b/gui/util.h @@ -0,0 +1,8 @@ +/** + * Given `total_levels', returns an integer between 4 and 12 which is a linear map of `level' onto `total_levels'. + * This is used for generating cache sizes given a number of levels. + * @param the total number of cache levels, zero-indexed. + * @param a numberedcache level, zero-indexed. + * @return an integer between 4-12, linearly scaled with level. + */ +int cache_size_mapper(int total_levels, int level); diff --git a/gui/worker.cc b/gui/worker.cc index 6419b73..93ccbea 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -17,6 +17,7 @@ #include "worker.h" #include "storage.h" +#include "util.h" Worker::Worker(QObject *parent) : QObject(parent) {} @@ -39,10 +40,6 @@ void Worker::configure( this->s.clear(); this->ct_mutex.lock(); - if (ways.size() != 0) { - // TODO optimal proper sizes - this->size_inc = ((MEM_LINE_SPEC * 0.75) / ways.size()); - } d = new Dram(DRAM_DELAY); s = static_cast(d); @@ -51,7 +48,8 @@ void Worker::configure( for (i = ways.size(); i > 0; --i) { s = static_cast(new Cache( - s, this->size_inc * (i), ways.at(i - 1), CACHE_DELAY + i)); + s, cache_size_mapper(ways.size() - 1, i), ways.at(i - 1), + CACHE_DELAY + i)); this->s.push_front(s); } diff --git a/gui/worker.h b/gui/worker.h index c0e72d3..c62f4ed 100644 --- a/gui/worker.h +++ b/gui/worker.h @@ -50,11 +50,6 @@ class Worker : public QObject Controller *ct = nullptr; QMutex ct_mutex; - /** - * The size each progressive cache level increases by. - */ - unsigned int size_inc; - public: explicit Worker(QObject *parent = nullptr); ~Worker(); -- cgit v1.2.3 From 94c0d7b5045244f20dfa13f7d31e0e06901908c2 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 12:32:34 -0400 Subject: Add a digit delegate to toggle table base display --- gui/digitlabeldelegate.cc | 57 +++++++++++++++++++++++++++++++++++++++++++++++ gui/digitlabeldelegate.h | 47 ++++++++++++++++++++++++++++++++++++++ gui/gui.cc | 12 ++++++++-- 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 gui/digitlabeldelegate.cc create mode 100644 gui/digitlabeldelegate.h diff --git a/gui/digitlabeldelegate.cc b/gui/digitlabeldelegate.cc new file mode 100644 index 0000000..641b5a0 --- /dev/null +++ b/gui/digitlabeldelegate.cc @@ -0,0 +1,57 @@ +// 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 "digitlabeldelegate.h" +#include "digitlabelhelper.h" +#include + +DigitLabelDelegate::DigitLabelDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ + ; +} + +void DigitLabelDelegate::set_hex_display(bool hex) +{ + if (this->is_hex != hex) { + this->is_hex = hex; + if (auto v = qobject_cast(parent())) + v->viewport()->update(); + } +} + +void DigitLabelDelegate::paint( + QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + int v; + QString t; + QStyleOptionViewItem o; + QStyle *s; + + v = index.data(Qt::DisplayRole).toInt(); + t = DigitLabelHelper::format_value(v, this->is_hex); + + o = option; + initStyleOption(&o, index); + o.text = t; + + const QWidget *w = option.widget; + s = w ? w->style() : QApplication::style(); + s->drawControl(QStyle::CE_ItemViewItem, &o, painter, w); +} diff --git a/gui/digitlabeldelegate.h b/gui/digitlabeldelegate.h new file mode 100644 index 0000000..a823154 --- /dev/null +++ b/gui/digitlabeldelegate.h @@ -0,0 +1,47 @@ +// 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 . + +#ifndef DIGITLABELDELEGATE_H +#define DIGITLABELDELEGATE_H + +#include +#include +#include +#include +#include +#include + +class DigitLabelDelegate : public QStyledItemDelegate +{ + Q_OBJECT + + public: + explicit DigitLabelDelegate(QObject *parent = nullptr); + + public slots: + void set_hex_display(bool hex); + + private: + bool is_hex = true; + + void paint( + QPainter *painter, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override; +}; + +#endif // DIGITLABELDELEGATE_H diff --git a/gui/gui.cc b/gui/gui.cc index ecdf9d3..80d4a2a 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -17,6 +17,7 @@ #include "gui.h" #include "./ui_gui.h" +#include "digitlabeldelegate.h" #include "dynamicwaysentry.h" #include "messages.h" #include "storageview.h" @@ -57,7 +58,6 @@ GUI::GUI(QWidget *parent) : QMainWindow(parent), ui(new Ui::GUI) for (DigitLabel *label : labels) { connect(this, &GUI::hex_toggled, label, &DigitLabel::on_hex_toggle); } - emit this->hex_toggled(this->is_hex); // display clock cycles and PC connect(worker, &Worker::clock_cycles, this, &GUI::on_worker_refresh_gui); @@ -345,6 +345,7 @@ void GUI::make_tabs(int num) StorageView *e; QTableView *t; QString n; + DigitLabelDelegate *d; ui->storage->clear(); @@ -361,11 +362,18 @@ void GUI::make_tabs(int num) e = new StorageView(MEM_LINES, this); } else { n = QString("L%1").arg(i - 1); - e = new StorageView(cache_size_mapper(this->curr_cache_levels, i), this); + e = new StorageView( + cache_size_mapper(this->curr_cache_levels, i), this); } t = new QTableView; t->setModel(e); + d = new DigitLabelDelegate(t); + + connect( + this, &GUI::hex_toggled, d, &DigitLabelDelegate::set_hex_display); + + t->setItemDelegate(d); t->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); ui->storage->addTab(t, n); -- cgit v1.2.3 From 1c174cc103cb1b00befed6e52b40bb3e76cc7797 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 14:29:48 -0400 Subject: Use two's complement in number display --- gui/digitlabel.h | 2 +- gui/digitlabelhelper.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/gui/digitlabel.h b/gui/digitlabel.h index 68b01cb..bffdd0a 100644 --- a/gui/digitlabel.h +++ b/gui/digitlabel.h @@ -59,7 +59,7 @@ class DigitLabel : public QLabel /** * If this digit should display in hexidecinmal. */ - int is_hex; + int is_hex = true; /** * If this digit should not display. */ diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h index a0f845f..715089a 100644 --- a/gui/digitlabelhelper.h +++ b/gui/digitlabelhelper.h @@ -24,7 +24,8 @@ class DigitLabelHelper { public: /** - * Contains the main formatting logic used to format integers. + * Contains the main formatting logic used to format integers. Uses 2's + * complement for hexadecimal numbers. * @param the value to be formated * @param if the value should be displayed in hex. If false, displays in * decimal. @@ -35,7 +36,7 @@ class DigitLabelHelper { if (is_cleared) return QString(); - return is_hex ? QString::number(value, 16).toUpper() + return is_hex ? QString::asprintf("%04X", value) : QString::number(value); } }; -- cgit v1.2.3 From b32bc409c18ceb4cd8147f11021e2c4b2746184b Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 14:41:02 -0400 Subject: right-align colum headers on table objects --- gui/digitlabeldelegate.cc | 6 ------ gui/digitlabeldelegate.h | 3 +-- gui/digitlabelhelper.h | 2 +- gui/storageview.cc | 7 +++++++ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gui/digitlabeldelegate.cc b/gui/digitlabeldelegate.cc index 641b5a0..bf4b175 100644 --- a/gui/digitlabeldelegate.cc +++ b/gui/digitlabeldelegate.cc @@ -19,12 +19,6 @@ #include "digitlabelhelper.h" #include -DigitLabelDelegate::DigitLabelDelegate(QObject *parent) - : QStyledItemDelegate(parent) -{ - ; -} - void DigitLabelDelegate::set_hex_display(bool hex) { if (this->is_hex != hex) { diff --git a/gui/digitlabeldelegate.h b/gui/digitlabeldelegate.h index a823154..7714d25 100644 --- a/gui/digitlabeldelegate.h +++ b/gui/digitlabeldelegate.h @@ -28,9 +28,8 @@ class DigitLabelDelegate : public QStyledItemDelegate { Q_OBJECT - public: - explicit DigitLabelDelegate(QObject *parent = nullptr); + using QStyledItemDelegate::QStyledItemDelegate; public slots: void set_hex_display(bool hex); diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h index 715089a..26e4637 100644 --- a/gui/digitlabelhelper.h +++ b/gui/digitlabelhelper.h @@ -36,7 +36,7 @@ class DigitLabelHelper { if (is_cleared) return QString(); - return is_hex ? QString::asprintf("%04X", value) + return is_hex ? QString::asprintf("%X", value) : QString::number(value); } }; diff --git a/gui/storageview.cc b/gui/storageview.cc index f6f9736..43837a9 100644 --- a/gui/storageview.cc +++ b/gui/storageview.cc @@ -48,6 +48,13 @@ QVariant StorageView::data(const QModelIndex &i, int role) const QVariant StorageView::headerData(int section, Qt::Orientation o, int role) const { + Qt::Alignment a; + + if (role == Qt::TextAlignmentRole) { + a = Qt::AlignRight | Qt::AlignVCenter; + return QVariant(static_cast(a)); + } + if (role != Qt::DisplayRole) return QVariant(); -- cgit v1.2.3 From ae2aaecfc1b2402a55e99cf674eff7b6175b0b6d Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 14:57:56 -0400 Subject: Basic hex formatting on row headers for storage tables --- gui/digitlabelhelper.h | 3 +-- gui/gui.cc | 3 ++- gui/storageview.cc | 15 +++++++++++++-- gui/storageview.h | 7 +++++++ 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h index 26e4637..4d45c68 100644 --- a/gui/digitlabelhelper.h +++ b/gui/digitlabelhelper.h @@ -36,8 +36,7 @@ class DigitLabelHelper { if (is_cleared) return QString(); - return is_hex ? QString::asprintf("%X", value) - : QString::number(value); + return is_hex ? QString::asprintf("%X", value) : QString::number(value); } }; diff --git a/gui/gui.cc b/gui/gui.cc index 80d4a2a..2555435 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -353,7 +353,6 @@ void GUI::make_tabs(int num) qDeleteAll(this->tab_boxes); for (i = 0; i < num; ++i) { - // make the name if (i == 0) { n = "Registers"; e = new StorageView(0, this); @@ -370,6 +369,8 @@ void GUI::make_tabs(int num) t->setModel(e); d = new DigitLabelDelegate(t); + connect( + this, &GUI::hex_toggled, e, &StorageView::set_hex_display); connect( this, &GUI::hex_toggled, d, &DigitLabelDelegate::set_hex_display); diff --git a/gui/storageview.cc b/gui/storageview.cc index 43837a9..22baca0 100644 --- a/gui/storageview.cc +++ b/gui/storageview.cc @@ -17,6 +17,7 @@ #include "storageview.h" #include "definitions.h" +#include "digitlabelhelper.h" #include #include @@ -59,12 +60,13 @@ QVariant StorageView::headerData(int section, Qt::Orientation o, int role) const return QVariant(); if (o == Qt::Vertical) { - return section * 4; + return DigitLabelHelper::format_value(section * 4, this->is_hex); } return QVariant(); } -Qt::ItemFlags StorageView::flags(const QModelIndex &i) const { +Qt::ItemFlags StorageView::flags(const QModelIndex &i) const +{ (void)i; return Qt::ItemIsEnabled; } @@ -75,3 +77,12 @@ void StorageView::set_data(const QVector> &data) this->d = data; endResetModel(); } + +void StorageView::set_hex_display(bool hex) +{ + if (this->is_hex != hex) { + beginResetModel(); + this->is_hex = hex; + endResetModel(); + } +} diff --git a/gui/storageview.h b/gui/storageview.h index 4956f23..0518d8f 100644 --- a/gui/storageview.h +++ b/gui/storageview.h @@ -72,11 +72,18 @@ class StorageView : public QAbstractTableModel */ void set_data(const QVector> &data); + public slots: + void set_hex_display(bool hex); + private: /** * The number of rows in this table. */ int r; + /** + * Whether or not the headers should be displayed in hex. + */ + bool is_hex = true; /** * The data this table displays. */ -- cgit v1.2.3 From 118427baa510419041c3f8e9c7a4616b93f01672 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 15:02:09 -0400 Subject: Decide to zero pad all hexadecimal numbers --- gui/digitlabelhelper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h index 4d45c68..744bf0f 100644 --- a/gui/digitlabelhelper.h +++ b/gui/digitlabelhelper.h @@ -36,7 +36,7 @@ class DigitLabelHelper { if (is_cleared) return QString(); - return is_hex ? QString::asprintf("%X", value) : QString::number(value); + return is_hex ? QString::asprintf("%08X", value) : QString::number(value); } }; -- cgit v1.2.3 From 6382d595cf947eb54249ff5fea20d8eb073ef3c1 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 15:11:19 -0400 Subject: Move digit formatter to util.h --- gui/digitlabel.cc | 4 ++-- gui/digitlabeldelegate.cc | 4 ++-- gui/digitlabelhelper.h | 43 ------------------------------------------- gui/storageview.cc | 4 ++-- gui/util.cc | 8 ++++++++ gui/util.h | 23 +++++++++++++++++++++-- 6 files changed, 35 insertions(+), 51 deletions(-) delete mode 100644 gui/digitlabelhelper.h diff --git a/gui/digitlabel.cc b/gui/digitlabel.cc index a24a1e1..f77c1fa 100644 --- a/gui/digitlabel.cc +++ b/gui/digitlabel.cc @@ -16,7 +16,7 @@ // along with this program. If not, see . #include "digitlabel.h" -#include "digitlabelhelper.h" +#include "util.h" #include "gui.h" DigitLabel::DigitLabel(QWidget *parent) : QLabel(parent) { setText(QString()); } @@ -43,6 +43,6 @@ void DigitLabel::on_hex_toggle(bool is_hex) void DigitLabel::update_display() { QString t; - t = DigitLabelHelper::format_value(this->v, this->is_hex, this->is_cleared); + t = format_toggled_value(this->v, this->is_hex, this->is_cleared); setText(t); } diff --git a/gui/digitlabeldelegate.cc b/gui/digitlabeldelegate.cc index bf4b175..430946c 100644 --- a/gui/digitlabeldelegate.cc +++ b/gui/digitlabeldelegate.cc @@ -16,7 +16,7 @@ // along with this program. If not, see . #include "digitlabeldelegate.h" -#include "digitlabelhelper.h" +#include "util.h" #include void DigitLabelDelegate::set_hex_display(bool hex) @@ -39,7 +39,7 @@ void DigitLabelDelegate::paint( QStyle *s; v = index.data(Qt::DisplayRole).toInt(); - t = DigitLabelHelper::format_value(v, this->is_hex); + t = format_toggled_value(v, this->is_hex); o = option; initStyleOption(&o, index); diff --git a/gui/digitlabelhelper.h b/gui/digitlabelhelper.h deleted file mode 100644 index 744bf0f..0000000 --- a/gui/digitlabelhelper.h +++ /dev/null @@ -1,43 +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 . - -#ifndef DIGITLABELHELPER_H -#define DIGITLABELHELPER_H - -#include - -class DigitLabelHelper -{ - public: - /** - * Contains the main formatting logic used to format integers. Uses 2's - * complement for hexadecimal numbers. - * @param the value to be formated - * @param if the value should be displayed in hex. If false, displays in - * decimal. - * @param if the value should display. - * @return a string respecting the above parameters. - */ - static QString format_value(int value, bool is_hex, bool is_cleared = false) - { - if (is_cleared) - return QString(); - return is_hex ? QString::asprintf("%08X", value) : QString::number(value); - } -}; - -#endif // DIGITLABELHELPER_H diff --git a/gui/storageview.cc b/gui/storageview.cc index 22baca0..2f444a9 100644 --- a/gui/storageview.cc +++ b/gui/storageview.cc @@ -17,7 +17,7 @@ #include "storageview.h" #include "definitions.h" -#include "digitlabelhelper.h" +#include "util.h" #include #include @@ -60,7 +60,7 @@ QVariant StorageView::headerData(int section, Qt::Orientation o, int role) const return QVariant(); if (o == Qt::Vertical) { - return DigitLabelHelper::format_value(section * 4, this->is_hex); + return format_toggled_value(section * 4, this->is_hex); } return QVariant(); } diff --git a/gui/util.cc b/gui/util.cc index ee75e56..72c0d87 100644 --- a/gui/util.cc +++ b/gui/util.cc @@ -1,4 +1,5 @@ #include "util.h" +#include int cache_size_mapper(int total_levels, int level) { @@ -14,3 +15,10 @@ int cache_size_mapper(int total_levels, int level) return r; } + +QString format_toggled_value(int value, bool is_hex, bool is_cleared) +{ + if (is_cleared) + return QString(); + return is_hex ? QString::asprintf("%X", value) : QString::number(value); +} diff --git a/gui/util.h b/gui/util.h index 87c33f6..8e9d308 100644 --- a/gui/util.h +++ b/gui/util.h @@ -1,8 +1,27 @@ +#ifndef UTIL_H +#define UTIL_H + +#include + /** - * Given `total_levels', returns an integer between 4 and 12 which is a linear map of `level' onto `total_levels'. - * This is used for generating cache sizes given a number of levels. + * Given `total_levels', returns an integer between 4 and 12 which is a linear + * map of `level' onto `total_levels'. This is used for generating cache sizes + * given a number of levels. * @param the total number of cache levels, zero-indexed. * @param a numberedcache level, zero-indexed. * @return an integer between 4-12, linearly scaled with level. */ int cache_size_mapper(int total_levels, int level); + +/** + * Contains the main formatting logic used to format integers. Uses 2's + * complement for hexadecimal numbers. + * @param the value to be formated + * @param if the value should be displayed in hex. If false, displays in + * decimal. + * @param if the value should display. + * @return a string respecting the above parameters. + */ +QString format_toggled_value(int value, bool is_hex, bool is_cleared = false); + +#endif // UTIL_H -- cgit v1.2.3 From d449750f789076459de8d47c2960a1279e543c32 Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 16:38:07 -0400 Subject: Fix some issues in GUI looking for memory leak --- gui/gui.cc | 19 +++++++++++-------- gui/gui.h | 4 ++-- gui/util.cc | 5 +++-- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/gui/gui.cc b/gui/gui.cc index 2555435..7df1bfc 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -349,28 +349,31 @@ void GUI::make_tabs(int num) ui->storage->clear(); - this->tab_boxes.clear(); qDeleteAll(this->tab_boxes); + this->tab_boxes.clear(); for (i = 0; i < num; ++i) { if (i == 0) { n = "Registers"; e = new StorageView(0, this); - } else if (i == 1) { + } else if (i == num - 1) { n = "DRAM"; - e = new StorageView(MEM_LINES, this); + e = new StorageView(4, this); } else { - n = QString("L%1").arg(i - 1); + n = QString("L%1").arg(i); e = new StorageView( - cache_size_mapper(this->curr_cache_levels, i), this); + // cache_size_mapper(this->curr_cache_levels-1, i-1) + 4, this); } + std::cout << "total levels: " << num << ":" + << this->curr_cache_levels - 1 << " level: " << i + << std::endl; - t = new QTableView; + t = new QTableView(ui->storage); t->setModel(e); d = new DigitLabelDelegate(t); - connect( - this, &GUI::hex_toggled, e, &StorageView::set_hex_display); + connect(this, &GUI::hex_toggled, e, &StorageView::set_hex_display); connect( this, &GUI::hex_toggled, d, &DigitLabelDelegate::set_hex_display); diff --git a/gui/gui.h b/gui/gui.h index 10c8f67..3db88ff 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -99,12 +99,12 @@ class GUI : public QMainWindow /** * Indicates if the program has been initialized. */ - bool ready; + bool ready = false; /** * The current number of cache levels. */ - int curr_cache_levels; + int curr_cache_levels = 0; /** * The list of storage displays. diff --git a/gui/util.cc b/gui/util.cc index 72c0d87..21bf0be 100644 --- a/gui/util.cc +++ b/gui/util.cc @@ -1,16 +1,17 @@ #include "util.h" +#include "definitions.h" #include int cache_size_mapper(int total_levels, int level) { const int y_min = 4; - const int y_max = 12; + const int y_max = MEM_LINES - 2; double f, r; if (total_levels <= 1) return 8; - f = level / total_levels; + f = level / (double)total_levels; r = y_min + f * (y_max - y_min); return r; -- cgit v1.2.3 From 270d5c95c46385b7f8c3ad5ffd1adb4ac5a43acb Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 23:49:35 -0400 Subject: Fix bug which caused a very large allocation --- gui/gui.cc | 9 +++------ gui/util.cc | 2 +- gui/worker.cc | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/gui/gui.cc b/gui/gui.cc index 7df1bfc..6e7da5f 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -358,16 +358,13 @@ void GUI::make_tabs(int num) e = new StorageView(0, this); } else if (i == num - 1) { n = "DRAM"; - e = new StorageView(4, this); + e = new StorageView(MEM_LINES, this); } else { n = QString("L%1").arg(i); e = new StorageView( - // cache_size_mapper(this->curr_cache_levels-1, i-1) - 4, this); + (1 << cache_size_mapper(this->curr_cache_levels - 1, i - 1)), + this); } - std::cout << "total levels: " << num << ":" - << this->curr_cache_levels - 1 << " level: " << i - << std::endl; t = new QTableView(ui->storage); t->setModel(e); diff --git a/gui/util.cc b/gui/util.cc index 21bf0be..f3486fb 100644 --- a/gui/util.cc +++ b/gui/util.cc @@ -5,7 +5,7 @@ int cache_size_mapper(int total_levels, int level) { const int y_min = 4; - const int y_max = MEM_LINES - 2; + const int y_max = MEM_LINE_SPEC - 2; double f, r; if (total_levels <= 1) diff --git a/gui/worker.cc b/gui/worker.cc index 93ccbea..f490fb4 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -48,7 +48,7 @@ void Worker::configure( for (i = ways.size(); i > 0; --i) { s = static_cast(new Cache( - s, cache_size_mapper(ways.size() - 1, i), ways.at(i - 1), + s, cache_size_mapper(ways.size() - 1, i - 1), ways.at(i - 1), CACHE_DELAY + i)); this->s.push_front(s); } -- cgit v1.2.3 From b6a4bcd0b9ea23d4c760127e77112aaaa30cef0d Mon Sep 17 00:00:00 2001 From: bd Date: Sat, 26 Apr 2025 23:58:06 -0400 Subject: Ensure each tab is linked to correct cache object --- gui/worker.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/gui/worker.cc b/gui/worker.cc index f490fb4..0ba364b 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -81,10 +81,8 @@ void Worker::update() this->ct_mutex.lock(); emit register_storage(this->ct->get_gprs()); - emit storage(this->data_to_QT(this->s.at(0)->get_data()), 1); - - for (i = 1; i < s.size(); ++i) - emit storage(this->data_to_QT(this->s.at(i - 1)->get_data()), i + 1); + for (i = 0; i < s.size(); ++i) + emit storage(this->data_to_QT(this->s.at(i)->get_data()), i + 1); emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); emit if_info(this->if_stage->get_instr()); -- cgit v1.2.3 From af643762a1627b85f779ea9d864393f7d7035e6a Mon Sep 17 00:00:00 2001 From: bd Date: Sun, 27 Apr 2025 00:04:56 -0400 Subject: Adjust cache size generation algorithm --- gui/util.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/util.cc b/gui/util.cc index f3486fb..b62ed81 100644 --- a/gui/util.cc +++ b/gui/util.cc @@ -5,11 +5,11 @@ int cache_size_mapper(int total_levels, int level) { const int y_min = 4; - const int y_max = MEM_LINE_SPEC - 2; + const int y_max = MEM_LINE_SPEC - 4; double f, r; - if (total_levels <= 1) - return 8; + if (total_levels <= 0) + return 7; f = level / (double)total_levels; r = y_min + f * (y_max - y_min); -- cgit v1.2.3 From 2c99a2eab1919af938c03418c551a1f035b99a5c Mon Sep 17 00:00:00 2001 From: bd Date: Sun, 27 Apr 2025 02:42:40 -0400 Subject: Add two new high-value step options in the step slider --- gui/gui.h | 2 +- gui/gui.ui | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/gui.h b/gui/gui.h index 3db88ff..5c95db5 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -138,7 +138,7 @@ class GUI : public QMainWindow /** * The possible step slider values. */ - QVector step_values = {1, 5, 20, 50, 250, 1000, 10000}; + QVector step_values = {1, 5, 20, 50, 250, 1000, 10000, 100000, 500000}; QThread workerThread; diff --git a/gui/gui.ui b/gui/gui.ui index a21a200..ec1c23b 100644 --- a/gui/gui.ui +++ b/gui/gui.ui @@ -630,7 +630,7 @@ 0 - 6 + 8 1 -- cgit v1.2.3 From a4dd1f00a5d0108058fb3bfbd5f399a507792859 Mon Sep 17 00:00:00 2001 From: bd Date: Sun, 27 Apr 2025 03:02:37 -0400 Subject: Add a slider value for 100 million cycles --- gui/gui.cc | 2 +- gui/gui.h | 2 +- gui/gui.ui | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/gui.cc b/gui/gui.cc index 6e7da5f..b4feda6 100644 --- a/gui/gui.cc +++ b/gui/gui.cc @@ -139,6 +139,7 @@ void GUI::on_worker_refresh_gui(int cycles, int pc) { ui->p_counter->set_value(pc); ui->cycle_counter->set_value(cycles); + this->set_status(get_waiting, "idle"); } void GUI::onWorkerFetchInfo(const InstrDTO *i) @@ -288,7 +289,6 @@ void GUI::on_step_btn_clicked() this->set_status(get_running, "busy"); int steps = step_values[ui->step_slider->value()]; emit sendRunSteps(steps); - this->set_status(get_waiting, "idle"); } void GUI::on_save_program_state_btn_clicked() diff --git a/gui/gui.h b/gui/gui.h index 5c95db5..830d852 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -138,7 +138,7 @@ class GUI : public QMainWindow /** * The possible step slider values. */ - QVector step_values = {1, 5, 20, 50, 250, 1000, 10000, 100000, 500000}; + QVector step_values = {1, 5, 20, 50, 250, 1000, 10000, 100000, 500000, 100000000}; QThread workerThread; diff --git a/gui/gui.ui b/gui/gui.ui index ec1c23b..67cca60 100644 --- a/gui/gui.ui +++ b/gui/gui.ui @@ -630,7 +630,7 @@ 0 - 8 + 9 1 -- cgit v1.2.3