diff options
author | bd <bdunaisky@umass.edu> | 2025-04-02 04:05:18 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-02 04:05:18 +0000 |
commit | 9fb95d655393777dde5929182f94de36f903821d (patch) | |
tree | 4462f35895737460a01fab891a15f87aba2efb70 | |
parent | 24f0bd8af57381ab3112b5774d4ad23ac80f0718 (diff) | |
parent | 3eeb345d673bee6d62b04fc8a8a95ab822dc1e45 (diff) |
Merge pull request #46 from bdunahu/bdunahu
Ensure all stages only do work if they are not 'OK'
-rw-r--r-- | gui/gui.cc | 6 | ||||
-rw-r--r-- | gui/worker.cc | 139 | ||||
-rw-r--r-- | inc/ex.h | 2 | ||||
-rw-r--r-- | inc/id.h | 4 | ||||
-rw-r--r-- | inc/instr.h | 8 | ||||
-rw-r--r-- | inc/instrDTO.h | 15 | ||||
-rw-r--r-- | inc/stage.h | 35 | ||||
-rw-r--r-- | inc/wb.h | 20 | ||||
-rw-r--r-- | src/sim/controller.cc | 7 | ||||
-rw-r--r-- | src/sim/dum.cc | 8 | ||||
-rw-r--r-- | src/sim/ex.cc | 70 | ||||
-rw-r--r-- | src/sim/id.cc | 36 | ||||
-rw-r--r-- | src/sim/if.cc | 5 | ||||
-rw-r--r-- | src/sim/instrDTO.cc | 7 | ||||
-rw-r--r-- | src/sim/mm.cc | 44 | ||||
-rw-r--r-- | src/sim/stage.cc | 59 | ||||
-rw-r--r-- | src/sim/wb.cc | 82 | ||||
-rw-r--r-- | tests/controller.cc | 405 | ||||
-rw-r--r-- | tests/ex.cc | 95 | ||||
-rw-r--r-- | tests/id.cc | 4 | ||||
-rw-r--r-- | tests/if.cc | 22 |
21 files changed, 827 insertions, 246 deletions
@@ -63,7 +63,7 @@ void displayArrayHTML(QTextEdit *textEdit, const std::array<int, GPR_NUM> &data) QString tableText = "<table border='1' cellspacing='0' cellpadding='8' style='border-collapse: collapse; width: 100%; border: 2px solid black;'>"; tableText += "<tr>"; - int index = 1; + int index = 0; for (int value : data) { tableText += QString("<td align='center' style='border: 2px solid black; min-width: 60px; padding: 10px;'>" "%1 <sup style='font-size: 10px; font-weight: bold; color: black;'>%2</sup>" @@ -83,7 +83,7 @@ void displayTableHTML(QTextEdit *textEdit, const std::vector<std::array<signed i textEdit->setReadOnly(false); QString tableText = "<table border='1' cellspacing='0' cellpadding='8' style='border-collapse: collapse; width: 100%; border: 2px solid black;'>"; - int index = 1; + int index = 0; for (const auto &row : data) { tableText += "<tr>"; for (signed int value : row) { @@ -118,7 +118,7 @@ void browseAndUploadFile(QTextEdit *textEdit) { QTextStream in(&file); QString content; - int lineNumber = 1; + int lineNumber = 0; while (!in.atEnd()) { QString line = in.readLine(); diff --git a/gui/worker.cc b/gui/worker.cc index ca3ec4b..685b46c 100644 --- a/gui/worker.cc +++ b/gui/worker.cc @@ -2,66 +2,111 @@ Worker::Worker(QObject *parent) : QObject(parent) {} -void Worker::doWork() { - qDebug() << "Initializing..."; - this->d = new Dram(0); +void Worker::doWork() +{ + qDebug() << "Initializing..."; + this->d = new Dram(0); this->c = new Cache(this->d, 0); - this->if_stage = new IF(nullptr); + this->if_stage = new IF(nullptr); this->id_stage = new ID(if_stage); this->ex_stage = new EX(id_stage); - this->mm_stage = new MM(ex_stage); - this->wb_stage = new WB(mm_stage); - this->ct = new Controller(wb_stage, this->c, true); - - emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); - emit dram_storage(this->d->view(0,32)); - emit cache_storage(this->c->view(0,8)); - emit register_storage(this->ct->get_gprs()); - - signed int w; - w = 0x11223344; - this->d->write_word(MEM, w, 0x0); - this->c->write_word(MEM, w, 0x0); - this->ct->set_gprs(0, w); + this->mm_stage = new MM(ex_stage); + this->wb_stage = new WB(mm_stage); + this->ct = new Controller(wb_stage, this->c, true); + + emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); + emit dram_storage(this->d->view(0, 32)); + emit cache_storage(this->c->view(0, 8)); + emit register_storage(this->ct->get_gprs()); + + signed int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, + b15, b16, b17, b18, b19; + std::vector<signed int> p; + + // I-TYPE / / / / + b0 = 0b00000010000000000001000000001101; // ADDI $2 $0 0x200; + b1 = 0b00000000000000010010100000001101; // ADDI $5 $0 0x1; + b2 = 0b00000000000000000010100010101101; // STORE $5 0($2); + // I-TYPE / / / / + b3 = 0b00000000000000100010100000001101; // ADDI $5 $0 0x2; + b4 = 0b00000000000000010010100010101101; // STORE $5 1($2); + // I-TYPE / / / / + b5 = 0b00000000000000110010100000001101; // ADDI $5 $0 0x3; + b6 = 0b00000000000000100010100010101101; // STORE $5 2($2); + // I-TYPE / / / / + b7 = 0b00000000000001000010100000001101; // ADDI $5 $0 0x4; + b8 = 0b00000000000000110010100010101101; // STORE $5 3($2); + // // I-TYPE / / / / + b9 = 0b00000000000000000010100000001101; // ADDI $5 $0 0x0; + // // I-TYPE / / / / + b10 = 0b00000000000000110011000000001101; // ADDI $6 $0 0x3; + // // J-TYPE / / / + b11 = 0b00000000000000000011100000001010; // JRL CHECK + // // R-TYPE / / / / / + b12 = 0b00000000000100100101000100000100; // ADD $9 $2 $5; + // // I-TYPE / / / / + b13 = 0b00000000000000000011101001000101; // LOAD $7 0($9); (RAW HAZARD)! + // // I-TYPE / / / / + b14 = 0b00000000000000010100001001000101; // LOAD $8 1($9); + // // R-TYPE / / / / / + b15 = 0b00000000000011101000001110000100; // ADD $7 $7 $8; + // I-TYPE / / / / + b16 = 0b00000000000000000011101001101101; // STORE $7 0($9); + b17 = 0b00000000000000010010100101001101; // ADDI $5 $5 0x1; + // // R-TYPE / / / / / + b18 = 0b00000000000111100101001101000000; // CMP $6 $5 + // // J-TYPE / / / + b19 = 0b11111111111111111100000000010110; // bgt LOOP + + p = {b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, + b10, b11, b12, b13, b14, b15, b16, b17, b18, b19}; + this->d->load(p); } -Worker::~Worker() { - emit finished(); - qDebug() << "Worker destructor called in thread:" << QThread::currentThread(); - delete this->ct; +Worker::~Worker() +{ + emit finished(); + qDebug() << "Worker destructor called in thread:" + << QThread::currentThread(); + delete this->ct; delete this->c; } - -void Worker::refreshDram() { - qDebug() << "Refreshing Dram"; - emit dram_storage(this->d->view(0,32)); +void Worker::refreshDram() +{ + qDebug() << "Refreshing Dram"; + emit dram_storage(this->d->view(0, 32)); } -void Worker::refreshCache() { - qDebug() << "Refreshing Dram"; - emit cache_storage(this->c->view(0,8)); +void Worker::refreshCache() +{ + qDebug() << "Refreshing Dram"; + emit cache_storage(this->c->view(0, 8)); } -void Worker::refreshRegisters() { - qDebug() << "Refreshing Registers"; - emit register_storage(this->ct->get_gprs()); +void Worker::refreshRegisters() +{ + qDebug() << "Refreshing Registers"; + emit register_storage(this->ct->get_gprs()); } -void Worker::runSteps(int steps) { - qDebug() << "Running for steps: " << steps; - this->ct->run_for(steps); - emit dram_storage(this->d->view(0,32)); - emit cache_storage(this->c->view(0,8)); - emit register_storage(this->ct->get_gprs()); - emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +void Worker::runSteps(int steps) +{ + qDebug() << "Running for steps: " << steps; + this->ct->run_for(steps); + emit dram_storage(this->d->view(0, 256)); + emit cache_storage(this->c->view(0, 8)); + emit register_storage(this->ct->get_gprs()); + emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); } -void Worker::runStep() { - qDebug() << "Running for 1 step " ; - this->ct->advance(OK); - emit dram_storage(this->d->view(0,32)); - emit cache_storage(this->c->view(0,8)); - emit register_storage(this->ct->get_gprs()); - emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); -}
\ No newline at end of file +void Worker::runStep() +{ + qDebug() << "Running for 1 step "; + this->ct->advance(WAIT); + emit dram_storage(this->d->view(0, 256)); + emit cache_storage(this->c->view(0, 8)); + emit register_storage(this->ct->get_gprs()); + qDebug() << "PC " << this->ct->get_pc(); + emit clock_cycles(this->ct->get_clock_cycle(), this->ct->get_pc()); +} @@ -25,7 +25,7 @@ class EX : public Stage */ std::unordered_map< Mnemonic, - std::function<void(signed int &s1, signed int s2, signed int s3)>> + std::function<void(signed int &s1, signed int s2, signed int s3, unsigned int pc)>> instr_map; }; @@ -66,8 +66,8 @@ class ID : public Stage */ void get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, Type &t); void decode_R_type(signed int &s1, signed int &s2, signed int &s3); - void decode_I_type(signed int &s1, signed int &s2, signed int &s3); - void decode_J_type(signed int &s1, signed int &s2); + 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); /** * Helper for `get_instr_fields`. * Given a raw instruction, returns the mnemonic and type. diff --git a/inc/instr.h b/inc/instr.h index d17613d..2b1807a 100644 --- a/inc/instr.h +++ b/inc/instr.h @@ -1,7 +1,6 @@ #ifndef INSTR_H #define INSTR_H #include <functional> -#include <iostream> #include <unordered_map> enum Mnemonic { @@ -45,12 +44,7 @@ enum Mnemonic { NOP, }; -enum Type { - R, - I, - J, - INV -}; +enum Type { R, I, J, INV }; namespace instr { diff --git a/inc/instrDTO.h b/inc/instrDTO.h index 8249122..b6dec06 100644 --- a/inc/instrDTO.h +++ b/inc/instrDTO.h @@ -47,6 +47,10 @@ class InstrDTO * @return the type of the instruction */ Type get_type(); + /** + * @return the program counter at the time this instruction was fetched + */ + unsigned int get_pc(); /** * @param set hist key @@ -72,11 +76,15 @@ class InstrDTO * @param the mnemonic of the instruction */ void set_mnemonic(Mnemonic); - + /** * @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); private: /** @@ -100,11 +108,14 @@ class InstrDTO * The mnemonic of the operation. */ Mnemonic mnemonic; - /** * Type of the instruction */ Type type; + /** + * The PC of the instruction + */ + unsigned int pc; }; #endif /* INSTRDTO_H_INCLUDED */ diff --git a/inc/stage.h b/inc/stage.h index 03048b0..51ab667 100644 --- a/inc/stage.h +++ b/inc/stage.h @@ -34,7 +34,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 STALLED when an operation completes. + * Must set the status to WAIT when the current instruction is evicted.. */ virtual InstrDTO *advance(Response p); @@ -47,31 +47,33 @@ class Stage * @param the condition code to retrieve, */ bool get_condition(CC c); - /** - * Sets the value of the PC register. + * Sets the bit in the condition code register corresponding to `c`. + * @param the condition code to set. + * @param the truthy value to set it to. */ - void set_pc(unsigned int pc); + void set_condition(CC c, bool v); /** * Squashes the pipeline. */ void squash(); + /** + * The set of registers currently checked out. + */ + static std::deque<signed int> checked_out; + protected: /** * The function expected to do the majority of the work. * - * Must set the status to OK when an operation is ready. + * Must set the status to OK when an operation is done. + * Must set the status to STALLED when an operation cannot be completed the + * current cycle. */ virtual void advance_helper() = 0; /** - * Sets the bit in the condition code register corresponding to `c`. - * @param the condition code to set. - * @param the truthy value to set it to. - */ - void set_condition(CC c, bool v); - /** * Helper for `check_out`. * Returns true if r are not checked out, false otherwise. * @param a list of register numbers. @@ -79,6 +81,12 @@ class Stage */ bool is_checked_out(signed int r); /** + * Stores `d` into the register indexed `v`. + * @param the register number. + * @param the value to store. + */ + void store_register(signed int v, signed int d); + /** * Returns the value of the register corresponding to `v`. * @param the register number. * @return the value in the associated register. @@ -112,11 +120,6 @@ class Stage * The current clock cycle. */ static int clock_cycle; - // TODO fix this comment after writeback stage - /** - * The set of registers currently checked out. - */ - static std::deque<signed int> checked_out; /** * A pointer to the next stage in the pipeline. */ @@ -14,9 +14,27 @@ class WB : public Stage */ WB(Stage *next); using Stage::advance; - + private: void advance_helper() override; + /** + * Performs the actual work of storing into a register. + */ + void write_handler(); + /** + * Performs the actual work of processing a jump instruction. + */ + void jump_handler(); + /** + * @return true if the current instruction is an R or I type and is not a + * STORE. + */ + bool should_write(); + /** + * @return true if the current instruction is a J type and is not a push. + * STORE. + */ + bool should_jump(); }; #endif /* WB_H_INCLUDED */ diff --git a/src/sim/controller.cc b/src/sim/controller.cc index 7e24b3d..65e5676 100644 --- a/src/sim/controller.cc +++ b/src/sim/controller.cc @@ -9,6 +9,7 @@ Controller::Controller(Stage *stage, Storage *storage, bool is_pipelined) this->storage = storage; this->is_pipelined = is_pipelined; this->pc = 0x0; + this->checked_out = {}; this->gprs = {0}; // grant side-door access this->id = SIDE; @@ -18,7 +19,7 @@ void Controller::run_for(int number) { int i; for (i = 0; i < number; ++i) { - this->advance(OK); + this->advance(WAIT); } } @@ -37,9 +38,11 @@ InstrDTO *Controller::advance(Response p) InstrDTO *r; r = this->next->advance(p); ++this->clock_cycle; + return r; } -void Controller::advance_helper() { +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 index dd16660..76d4acd 100644 --- a/src/sim/dum.cc +++ b/src/sim/dum.cc @@ -9,13 +9,12 @@ DUM::DUM(Stage *stage) : Stage(stage) { this->id = IDLE; } InstrDTO *DUM::advance(Response p) { - InstrDTO *r = curr_instr; + InstrDTO *r = nullptr; - this->advance_helper(); - if (this->status == OK && p == OK) { + if (this->curr_instr && p == WAIT) { this->curr_instr->set_time_of(this->id, this->clock_cycle); r = new InstrDTO(*this->curr_instr); - delete curr_instr; + delete this->curr_instr; curr_instr = nullptr; } @@ -27,5 +26,4 @@ void DUM::advance_helper() {} void DUM::set_curr_instr(InstrDTO *d) { this->curr_instr = d; - this->status = OK; } diff --git a/src/sim/ex.cc b/src/sim/ex.cc index f22adc0..b6f8a1d 100644 --- a/src/sim/ex.cc +++ b/src/sim/ex.cc @@ -4,11 +4,12 @@ #include "instrDTO.h" #include "response.h" #include "stage.h" +#include "utils.h" #include <unordered_map> // clang-format off #define INIT_INSTRUCTION(mnemonic, body) \ - {mnemonic, [this](signed int &s1, signed int s2, signed int s3) { \ + {mnemonic, [this](signed int &s1, signed int s2, signed int s3, unsigned int pc) { \ body; \ }} // clang-format on @@ -23,6 +24,7 @@ EX::EX(Stage *stage) : Stage(stage) ADD, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -31,6 +33,7 @@ EX::EX(Stage *stage) : Stage(stage) SUB, { s1 = s1 - s2; + (void)pc; (void)s3; (void)this; }), @@ -39,6 +42,7 @@ EX::EX(Stage *stage) : Stage(stage) MUL, { s1 = s1 * s2; + (void)pc; (void)s3; (void)this; }), @@ -47,6 +51,7 @@ EX::EX(Stage *stage) : Stage(stage) QUOT, { s1 = s1 / s2; + (void)pc; (void)s3; (void)this; }), @@ -55,6 +60,7 @@ EX::EX(Stage *stage) : Stage(stage) REM, { s1 = s1 % s2; + (void)pc; (void)s3; (void)this; }), @@ -63,6 +69,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTR, { s1 = s1 >> s2; + (void)pc; (void)s3; (void)this; }), @@ -71,6 +78,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTL, { s1 = s1 << s2; + (void)pc; (void)s3; (void)this; }), @@ -79,6 +87,7 @@ EX::EX(Stage *stage) : Stage(stage) AND, { s1 = s1 & s2; + (void)pc; (void)s3; (void)this; }), @@ -87,6 +96,7 @@ EX::EX(Stage *stage) : Stage(stage) OR, { s1 = s1 | s2; + (void)pc; (void)s3; (void)this; }), @@ -95,6 +105,7 @@ EX::EX(Stage *stage) : Stage(stage) NOT, { s1 = ~s1; + (void)pc; (void)s3; (void)s2; (void)this; @@ -104,6 +115,7 @@ EX::EX(Stage *stage) : Stage(stage) XOR, { s1 = s1 ^ s2; + (void)pc; (void)s3; (void)this; }), @@ -111,6 +123,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( ADDV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -120,6 +133,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( SUBV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -129,6 +143,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( MULV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -138,6 +153,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( DIVV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -151,12 +167,14 @@ EX::EX(Stage *stage) : Stage(stage) : 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; @@ -168,6 +186,7 @@ EX::EX(Stage *stage) : Stage(stage) LOAD, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -175,6 +194,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( LOADV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -185,6 +205,7 @@ EX::EX(Stage *stage) : Stage(stage) ADDI, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -193,6 +214,7 @@ EX::EX(Stage *stage) : Stage(stage) SUBI, { s1 = s1 - s3; + (void)pc; (void)s2; (void)this; }), @@ -201,6 +223,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTRI, { s1 = s1 >> s3; + (void)pc; (void)s2; (void)this; }), @@ -209,6 +232,7 @@ EX::EX(Stage *stage) : Stage(stage) SFTLI, { s1 = s1 << s3; + (void)pc; (void)s2; (void)this; }), @@ -217,6 +241,7 @@ EX::EX(Stage *stage) : Stage(stage) ANDI, { s1 = s1 & s3; + (void)pc; (void)s2; (void)this; }), @@ -225,6 +250,7 @@ EX::EX(Stage *stage) : Stage(stage) ORI, { s1 = s1 | s3; + (void)pc; (void)s2; (void)this; }), @@ -233,6 +259,7 @@ EX::EX(Stage *stage) : Stage(stage) XORI, { s1 = s1 ^ s3; + (void)pc; (void)s2; (void)this; }), @@ -241,6 +268,7 @@ EX::EX(Stage *stage) : Stage(stage) STORE, { s1 = s1 + s3; + (void)pc; (void)s2; (void)this; }), @@ -248,6 +276,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( STOREV, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -259,6 +288,7 @@ EX::EX(Stage *stage) : Stage(stage) JMP, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -266,7 +296,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( JRL, { - s1 = this->pc + s2; + s1 = pc + s2; (void)s3; (void)this; }), @@ -275,6 +305,7 @@ EX::EX(Stage *stage) : Stage(stage) JAL, { s1 = s1 + s2; + (void)pc; (void)s3; (void)this; }), @@ -282,34 +313,39 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( BEQ, { - (this->get_condition(EQ)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(EQ)) ? s1 = wrap_address(pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BGT, { - (this->get_condition(GT)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(GT)) ? s1 = wrap_address(pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BUF, { - (this->get_condition(UF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(UF)) ? s1 = wrap_address(pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( BOF, { - (this->get_condition(OF)) ? s1 = this->pc + s2 : s1 = this->pc; + (this->get_condition(OF)) ? s1 = wrap_address(pc + s2) + : s1 = -1; (void)s3; }), INIT_INSTRUCTION( PUSH, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -319,6 +355,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( POP, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -329,6 +366,7 @@ EX::EX(Stage *stage) : Stage(stage) INIT_INSTRUCTION( NOP, { + (void)pc; (void)s3; (void)s2; (void)s1; @@ -340,19 +378,17 @@ EX::EX(Stage *stage) : Stage(stage) void EX::advance_helper() { signed int s1, s2, s3; + unsigned int pc; Mnemonic m; - // it may be good to ensure we are not doing - // work that has already been done - if (this->curr_instr) { - m = this->curr_instr->get_mnemonic(); - s1 = this->curr_instr->get_s1(); - s2 = this->curr_instr->get_s2(); - s3 = this->curr_instr->get_s3(); + 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); + this->instr_map[m](s1, s2, s3, pc ); - this->curr_instr->set_s1(s1); - this->status = OK; - } + this->curr_instr->set_s1(s1); + this->status = OK; } diff --git a/src/sim/id.cc b/src/sim/id.cc index 0b75b64..0c0be91 100644 --- a/src/sim/id.cc +++ b/src/sim/id.cc @@ -48,11 +48,11 @@ void ID::advance_helper() Mnemonic m; Type t; - // it may be good to ensure we are not doing - // work that has already been done - if (this->curr_instr && this->curr_instr->get_mnemonic() == NONE) { + if (curr_instr->get_mnemonic() == NOP) + this->status = OK; + else { s1 = curr_instr->get_instr_bits(); - get_instr_fields(s1, s2, s3, m ,t); + get_instr_fields(s1, s2, s3, m, t); if (this->status == OK) { curr_instr->set_s1(s1); curr_instr->set_s2(s2); @@ -63,7 +63,8 @@ void ID::advance_helper() } } -void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemonic &m, 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); @@ -75,11 +76,11 @@ void ID::get_instr_fields(signed int &s1, signed int &s2, signed int &s3, Mnemon break; case 0b01: t = I; - this->decode_I_type(s1, s2, s3); + this->decode_I_type(s1, s2, s3, m); break; case 0b10: t = J; - this->decode_J_type(s1, s2); + this->decode_J_type(s1, s2, s3); break; case 0b11: t = INV; @@ -101,14 +102,17 @@ void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3) r1 = this->read_guard(s1); r2 = this->read_guard(s2); - this->write_guard(s3); - this->status = (r1 == OK && r2 == OK) ? OK : STALLED; + + if (this->status == OK) + this->write_guard(s3); } -void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3) +void ID::decode_I_type( + signed int &s1, signed int &s2, signed int &s3, Mnemonic &m) { unsigned int s0b, s1b, s2b; + Response r1; s0b = REG_SIZE; s1b = s0b + REG_SIZE; @@ -117,16 +121,22 @@ void ID::decode_I_type(signed int &s1, signed int &s2, signed int &s3) s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); - this->status = this->read_guard(s1); - this->write_guard(s2); + r1 = this->read_guard(s1); + if (m != STORE && m != STOREV) { + this->status = r1; + if (r1 == OK) + this->write_guard(s2); + } else + this->status = (this->read_guard(s2) == OK && r1 == OK) ? OK : STALLED; } -void ID::decode_J_type(signed int &s1, signed int &s2) +void ID::decode_J_type(signed int &s1, signed int &s2, signed int &s3) { unsigned int s0b, s1b; s0b = REG_SIZE; s1b = WORD_SPEC; + s3 = 0; s2 = GET_MID_BITS(s1, s0b, s1b); s1 = GET_LS_BITS(s1, s0b); diff --git a/src/sim/if.cc b/src/sim/if.cc index fa8f6c2..85fb27f 100644 --- a/src/sim/if.cc +++ b/src/sim/if.cc @@ -11,14 +11,13 @@ InstrDTO *IF::advance(Response p) InstrDTO *r = nullptr; this->advance_helper(); - if (this->curr_instr != nullptr && p == OK) { + if (this->curr_instr != nullptr && p == WAIT) { // mutual consent ++this->pc; this->curr_instr->set_time_of(this->id, this->clock_cycle); r = new InstrDTO(*this->curr_instr); delete curr_instr; curr_instr = nullptr; - this->status = STALLED; } return r; @@ -32,9 +31,9 @@ void IF::advance_helper() if (this->curr_instr == nullptr) { r = this->storage->read_word(this->id, this->pc, bits); if (r == OK) { - this->status = r; this->curr_instr = new InstrDTO(); this->curr_instr->set_instr_bits(bits); + this->curr_instr->set_pc(this->pc); } } } diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc index b33c26b..aa49b7e 100644 --- a/src/sim/instrDTO.cc +++ b/src/sim/instrDTO.cc @@ -7,8 +7,9 @@ InstrDTO::InstrDTO() this->s1 = 0; this->s2 = 0; this->s3 = 0; - this->mnemonic = NONE; + this->mnemonic = ADD; this->type = INV; + this->pc = 0; } int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; } @@ -25,6 +26,8 @@ Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; } Type InstrDTO::get_type() { return this->type; } +unsigned int InstrDTO::get_pc() { return this->pc; } + void InstrDTO::set_time_of(Accessor a, int i) { this->hist[a] = i; } void InstrDTO::set_instr_bits(signed int instr) { this->instr_bits = instr; } @@ -38,3 +41,5 @@ 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; } diff --git a/src/sim/mm.cc b/src/sim/mm.cc index cd85056..07a362b 100644 --- a/src/sim/mm.cc +++ b/src/sim/mm.cc @@ -4,26 +4,32 @@ #include "response.h" #include "stage.h" -MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } +MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; } -void MM::advance_helper() { - Response r; +void MM::advance_helper() +{ signed int data; - if(this->curr_instr){ - if (this->curr_instr->get_mnemonic() == LOAD) { - r = this->storage->read_word(this->id, this->curr_instr->get_s1(), data); - if(r == OK){ - this->status = OK; - this->curr_instr->set_s2(data); - } - } else if (this->curr_instr->get_mnemonic() == STORE) { - r = this->storage->write_word(this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); - if(r == OK){ - this->status = OK; - } - } else { - // Mem has no work so just forward the instruction to WB - this->status = OK; + + switch (this->curr_instr->get_mnemonic()) { + case LOAD: + this->status = this->storage->read_word( + this->id, this->curr_instr->get_s1(), data); + if (this->status == OK) { + this->curr_instr->set_s1(data); + } else + this->status = STALLED; + break; + + case STORE: + // TODO signed issues, we aren't wrapping addresses + this->status = this->storage->write_word( + this->id, this->curr_instr->get_s2(), this->curr_instr->get_s1()); + if (this->status != OK) { + this->status = STALLED; } - } + break; + + default: + this->status = OK; + } } diff --git a/src/sim/stage.cc b/src/sim/stage.cc index be69d77..2857e1f 100644 --- a/src/sim/stage.cc +++ b/src/sim/stage.cc @@ -7,8 +7,7 @@ Stage::Stage(Stage *next) { this->next = next; this->curr_instr = nullptr; - this->status = OK; - this->checked_out = {}; + this->status = WAIT; } Stage::~Stage() { delete this->next; }; @@ -21,32 +20,36 @@ Storage *Stage::storage; bool Stage::is_pipelined; int Stage::clock_cycle; -bool Stage::get_condition(CC c) { - return (this->gprs[3] >> c) & 1; -} - -void Stage::set_pc(unsigned int pc) { - this->pc = pc; -} +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; - this->advance_helper(); - if (this->status == OK && this->curr_instr != nullptr && p == OK) { + // 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->status != OK) { + this->advance_helper(); + } + if (this->status == OK && p == WAIT && this->curr_instr) { // mutual consent this->curr_instr->set_time_of(this->id, this->clock_cycle); r = new InstrDTO(*this->curr_instr); delete curr_instr; curr_instr = nullptr; - this->status = STALLED; + this->status = WAIT; } - n = (p != OK || this->status != OK) ? STALLED : OK; - // the power of consent - this->curr_instr = this->next->advance(n); + n = (p != WAIT || this->status != WAIT) ? STALLED : WAIT; + s = this->next->advance(n); + if (s) + this->curr_instr = s; return r; } @@ -73,16 +76,34 @@ signed int Stage::dereference_register(signed int 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(string_format( + "instruction tried to access register %d, which does " + "not exist", + v)); + } + + 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(){ - this->curr_instr->set_mnemonic(NOP); - this->status = OK; - if(this->next){ +void Stage::squash() +{ + if (curr_instr) { + this->curr_instr->set_mnemonic(NOP); + this->status = OK; + } + if (this->next) { this->next->squash(); } } diff --git a/src/sim/wb.cc b/src/sim/wb.cc index ac47f25..01768e8 100644 --- a/src/sim/wb.cc +++ b/src/sim/wb.cc @@ -6,34 +6,56 @@ WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; } -void WB::advance_helper() { - if(this -> curr_instr) { - if(this->curr_instr->get_type() == R || this->curr_instr->get_type() == I){ - if(this->checked_out.size() > 0) { - signed int reg = this->checked_out.front(); - this->checked_out.pop_front(); - if(reg >= GPR_NUM){ - // TODO: handle vector instructions - } else { - if(this->curr_instr->get_mnemonic() != STORE && this->curr_instr->get_mnemonic() != STOREV){ - this->gprs[reg] = this->curr_instr->get_s1(); - } - } - } - } else if (this->curr_instr->get_type() == J) { - // TODO:handle push pop - // branch taken - if(this->pc != this->curr_instr->get_s1()) { - if(this->curr_instr->get_mnemonic() == JAL){ - // set link register to next instruction - this->gprs[1] = this->pc + 1; - } - this->pc = this->curr_instr->get_s1(); - //clear pending registers and squash pipeline - this->checked_out = {}; - this->next->squash(); - } - } - } - this->status = OK; +void WB::advance_helper() +{ + if (this->curr_instr->get_mnemonic() != NOP && + this->curr_instr->get_type() != INV) { + if (this->should_write()) + 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."); + + reg = this->checked_out.front(); + this->checked_out.pop_front(); + 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->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; +} + +bool WB::should_write() +{ + Mnemonic m; + Type t; + + m = this->curr_instr->get_mnemonic(); + t = this->curr_instr->get_type(); + return (t == R || t == I) && (m != STORE && m != STOREV); } diff --git a/tests/controller.cc b/tests/controller.cc index de49629..a009a70 100644 --- a/tests/controller.cc +++ b/tests/controller.cc @@ -21,15 +21,27 @@ class ControllerPipeFixture IF *f = new IF(nullptr); ID *d = new ID(f); EX *e = new EX(d); + MM *m = new MM(e); + WB *w = new WB(m); + this->stage_num = 5; - this->ct = new Controller(e, this->c, true); + this->ct = new Controller(w, this->c, true); } ~ControllerPipeFixture() { delete this->ct; delete this->c; }; - + void fill_pipe() + { + InstrDTO *i = nullptr; + int j; + for (j = 0; j < this->stage_num + 1; ++j) { + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + } + } + int stage_num; Cache *c; Dram *d; Controller *ct; @@ -51,40 +63,387 @@ TEST_CASE_METHOD( CHECK(this->ct->get_pc() == 0); } -TEST_CASE_METHOD(ControllerPipeFixture, "Add until exec", "[tmp]") +TEST_CASE_METHOD(ControllerPipeFixture, "two num adder", "[full pipe]") { - signed int b; + signed int b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, + b15; std::vector<signed int> p; InstrDTO *i; - b = 0b1010100000000001001101; - p = {b}; + // I-TYPE / / / / + b0 = 0b00000010000000000001000000001101; // ADDI $2 $0 0x200; + b1 = 0b00000000000000010010100000001101; // ADDI $5 $0 0x1; + b2 = 0b00000000000000000010100010101101; // STORE $5 0($2); (RAW HAZARD w + // 1)! + // I-TYPE / / / / + b3 = 0b00000000000000100010100000001101; // ADDI $5 $0 0x2; (RAW HAZARD)! + b4 = 0b00000000000000010010100010101101; // STORE $5 1($2); (RAW HAZARD)! + // // I-TYPE / / / / + b5 = 0b00000000000000000010100000001101; // ADDI $5 $0 0x0; + // // I-TYPE / / / / + b6 = 0b00000000000000010011000000001101; // ADDI $6 $0 0x1; + // // J-TYPE / / / + b7 = 0b00000000000000000011100000001010; // JRL CHECK + // // R-TYPE / / / / / + b8 = 0b00000000000100100101000100000100; // ADD $9 $2 $5; + // // I-TYPE / / / / + b9 = 0b00000000000000000011101001000101; // LOAD $7 0($9); (RAW HAZARD)! + // // I-TYPE / / / / + b10 = 0b00000000000000010100001001000101; // LOAD $8 1($9); + // // R-TYPE / / / / / + b11 = 0b00000000000011101000001110000100; // ADD $7 $7 $8; + // I-TYPE / / / / + b12 = 0b00000000000000000011101001101101; // STORE $7 0($9); + b13 = 0b00000010000000010010100101001101; // ADDI $5 $5 0x1; + // // R-TYPE / / / / / + b14 = 0b00000000000111100101001101000000; // CMP $6 $5 + // // J-TYPE / / / + b15 = 0b11111111111111111100100000010110; // bgt LOOP + + p = {b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15}; this->d->load(p); - // dram - i = this->ct->advance(OK); + this->fill_pipe(); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 3); + CHECK(i->get_time_of(DCDE) == 4); + CHECK(i->get_time_of(EXEC) == 5); + CHECK(i->get_time_of(MEM) == 6); + CHECK(i->get_time_of(WRITE) == 7); + CHECK(i->get_s1() == 0x200); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x200); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b0); + CHECK(this->ct->checked_out.front() == 0x5); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 4); + CHECK(i->get_time_of(DCDE) == 5); + CHECK(i->get_time_of(EXEC) == 6); + CHECK(i->get_time_of(MEM) == 7); + CHECK(i->get_time_of(WRITE) == 8); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x1); + CHECK(this->ct->get_gprs().at(5) == 0x1); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b1); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // fetch - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // decode - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // exec - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - // done - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); REQUIRE(i != nullptr); - CHECK(i->get_time_of(FETCH) == 3); - CHECK(i->get_time_of(DCDE) == 4); - CHECK(i->get_time_of(EXEC) == 5); - CHECK(i->get_s1() == 42); - CHECK(i->get_s2() == 0); - CHECK(i->get_s3() == 42); + CHECK(i->get_time_of(FETCH) == 5); + CHECK( + i->get_time_of(DCDE) == + 8); // the previous conflicting instruction wrote here! + CHECK(i->get_time_of(EXEC) == 9); + CHECK(i->get_time_of(MEM) == 14); // waited for fetch + 3 dram + CHECK(i->get_time_of(WRITE) == 15); + CHECK(i->get_s1() == 0x200); + CHECK(i->get_s2() == 0x1); + CHECK(i->get_s3() == 0x0); + // NO STORE + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x1); + CHECK(i->get_mnemonic() == STORE); + CHECK(i->get_instr_bits() == b2); + CHECK(this->ct->checked_out.front() == 0x5); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 8); + CHECK(i->get_time_of(DCDE) == 9); + CHECK(i->get_time_of(EXEC) == 14); + CHECK(i->get_time_of(MEM) == 15); + CHECK(i->get_time_of(WRITE) == 16); + CHECK(i->get_s1() == 0x2); + CHECK(i->get_s2() == 0x1); // the previous value in the destination register + CHECK(i->get_s3() == 0x2); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x2); CHECK(i->get_mnemonic() == ADDI); - CHECK(i->get_instr_bits() == b); + CHECK(i->get_instr_bits() == b3); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 14); // fetching new line + mem + CHECK( + i->get_time_of(DCDE) == + 16); // the previous conflicting instruction wrote here! + CHECK(i->get_time_of(EXEC) == 17); + CHECK(i->get_time_of(MEM) == 18); + CHECK(i->get_time_of(WRITE) == 19); + CHECK(i->get_s1() == 0x201); + CHECK(i->get_s2() == 0x2); // address + CHECK(i->get_s3() == 0x1); // offset + // NO STORE + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x2); + CHECK(i->get_mnemonic() == STORE); + CHECK(i->get_instr_bits() == b4); + // CHECK(this->ct->checked_out.front() == 0x5); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 16); + CHECK(i->get_time_of(DCDE) == 17); + CHECK(i->get_time_of(EXEC) == 18); + CHECK(i->get_time_of(MEM) == 19); + CHECK(i->get_time_of(WRITE) == 20); + CHECK(i->get_s1() == 0x0); + CHECK(i->get_s2() == 0x2); + CHECK(i->get_s3() == 0x0); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x0); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b5); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 17); + CHECK(i->get_time_of(DCDE) == 18); + CHECK(i->get_time_of(EXEC) == 19); + CHECK(i->get_time_of(MEM) == 20); + CHECK(i->get_time_of(WRITE) == 21); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x1); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(i->get_pc() == 0x6); + CHECK(this->ct->get_pc() == 0x9); + CHECK(i->get_mnemonic() == ADDI); + CHECK(i->get_instr_bits() == b6); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 18); + CHECK(i->get_time_of(DCDE) == 19); + CHECK(i->get_time_of(EXEC) == 20); + CHECK(i->get_time_of(MEM) == 21); + CHECK(i->get_time_of(WRITE) == 22); + CHECK(i->get_s1() == 0xE); + CHECK(i->get_s2() == 0x7); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(i->get_pc() == 0x7); + CHECK(this->ct->get_pc() == 0xE); + CHECK(i->get_mnemonic() == JRL); + CHECK(i->get_instr_bits() == b7); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); // switching cache lines in fetch + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_mnemonic() == NOP); // squashed + + delete i; + i = this->ct->advance(WAIT); // nops? + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK( + i->get_time_of(FETCH) == + 24); // 6 greater than last fetch (4 flush pipe, 2 dram) + CHECK(i->get_time_of(DCDE) == 25); + CHECK(i->get_time_of(EXEC) == 26); + CHECK(i->get_time_of(MEM) == 27); + CHECK(i->get_time_of(WRITE) == 28); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x0); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x0); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_condition(GT) == true); + CHECK(this->ct->get_condition(EQ) == false); + CHECK(i->get_mnemonic() == CMP); + CHECK(i->get_instr_bits() == b14); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 25); + CHECK(i->get_time_of(DCDE) == 26); + CHECK(i->get_time_of(EXEC) == 27); + CHECK(i->get_time_of(MEM) == 28); + CHECK(i->get_time_of(WRITE) == 29); + CHECK(i->get_s1() == 0x8); + CHECK(i->get_s2() == 0b111111111111111111001); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(5) == 0x0); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_condition(GT) == true); + CHECK(this->ct->get_condition(EQ) == false); + CHECK(this->ct->get_pc() == 0x9); + CHECK(i->get_mnemonic() == BGT); + CHECK(i->get_instr_bits() == b15); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_mnemonic() == NOP); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); // it was already in cache + + CHECK(i->get_time_of(FETCH) == 29); // clear out pipe (4) + CHECK(i->get_time_of(DCDE) == 30); + CHECK(i->get_time_of(EXEC) == 31); + CHECK(i->get_time_of(MEM) == 32); + CHECK(i->get_time_of(WRITE) == 33); + CHECK(i->get_s1() == 0x200); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x0); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_gprs().at(9) == 0x200); + CHECK(i->get_pc() == 0x8); + CHECK(this->ct->get_pc() == 0xB); + CHECK(i->get_mnemonic() == ADD); + CHECK(i->get_instr_bits() == b8); + CHECK(this->ct->checked_out.front() == 0x7); + + delete i; + i = this->ct->advance(WAIT); // RAW + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 30); + CHECK(i->get_time_of(DCDE) == 33); + CHECK(i->get_time_of(EXEC) == 34); + CHECK(i->get_time_of(MEM) == 35); + CHECK(i->get_time_of(WRITE) == 36); + CHECK(i->get_s1() == 0x1); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x0); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_gprs().at(7) == 0x1); + CHECK(this->ct->get_gprs().at(9) == 0x200); + CHECK(i->get_mnemonic() == LOAD); + CHECK(i->get_instr_bits() == b9); + CHECK(this->ct->checked_out.front() == 0x8); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 33); + CHECK(i->get_time_of(DCDE) == 34); + CHECK(i->get_time_of(EXEC) == 35); + CHECK(i->get_time_of(MEM) == 36); + CHECK(i->get_time_of(WRITE) == 37); + CHECK(i->get_s1() == 0x2); + CHECK(i->get_s2() == 0x0); + CHECK(i->get_s3() == 0x1); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_gprs().at(7) == 0x1); + CHECK(this->ct->get_gprs().at(8) == 0x2); + CHECK(this->ct->get_gprs().at(9) == 0x200); + CHECK(i->get_mnemonic() == LOAD); + CHECK(i->get_instr_bits() == b10); + CHECK(this->ct->checked_out.front() == 0x7); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 34); + CHECK(i->get_time_of(DCDE) == 37); + CHECK(i->get_time_of(EXEC) == 38); + CHECK(i->get_time_of(MEM) == 39); + CHECK(i->get_time_of(WRITE) == 40); + CHECK(i->get_s1() == 0x3); + CHECK(i->get_s2() == 0x2); + CHECK(i->get_s3() == 0x1); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_gprs().at(7) == 0x3); + CHECK(this->ct->get_gprs().at(8) == 0x2); + CHECK(this->ct->get_gprs().at(9) == 0x200); + CHECK(i->get_mnemonic() == ADD); + CHECK(i->get_instr_bits() == b11); + + delete i; + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i == nullptr); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); + + CHECK(i->get_time_of(FETCH) == 37); + CHECK(i->get_time_of(DCDE) == 40); + CHECK(i->get_time_of(EXEC) == 41); + CHECK(i->get_time_of(MEM) == 42); + CHECK(i->get_time_of(WRITE) == 43); + CHECK(i->get_s1() == 0x200); + CHECK(i->get_s2() == 0x3); + CHECK(i->get_s3() == 0x0); + CHECK(this->ct->get_gprs().at(2) == 0x200); + CHECK(this->ct->get_gprs().at(6) == 0x1); + CHECK(this->ct->get_gprs().at(7) == 0x3); + CHECK(this->ct->get_gprs().at(8) == 0x2); + CHECK(this->ct->get_gprs().at(9) == 0x200); + CHECK(i->get_mnemonic() == STORE); + CHECK(i->get_instr_bits() == b12); delete i; } diff --git a/tests/ex.cc b/tests/ex.cc index 9543c66..13437f7 100644 --- a/tests/ex.cc +++ b/tests/ex.cc @@ -33,9 +33,9 @@ class EXFixture i->set_mnemonic(m); this->dum->set_curr_instr(i); - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i != nullptr); return i; @@ -640,8 +640,7 @@ TEST_CASE_METHOD(EXFixture, "JRL", "[ex]") InstrDTO *i; m = JRL; - s1 = 100, s2 = -42027, s3 = 0; - this->ct->set_pc(42096); + s1 = 100, s2 = 69, s3 = 0; i = execute_instr(s1, s2, s3, m); CHECK(i->get_s1() == 69); @@ -668,6 +667,21 @@ TEST_CASE_METHOD(EXFixture, "JAL", "[ex]") delete i; } +TEST_CASE_METHOD(EXFixture, "BEQ no cond", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = BEQ; + s1 = 100, s2 = 50, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -1); + + delete i; +} + TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]") { signed int s1, s2, s3; @@ -675,13 +689,26 @@ TEST_CASE_METHOD(EXFixture, "BEQ", "[ex]") InstrDTO *i; m = BEQ; - s1 = 100, s2 = -42027, s3 = 0; - this->ct->set_pc(42096); + s1 = 100, s2 = 50, s3 = 0; + this->ct->set_condition(EQ, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); - CHECK(!ct->get_condition(OF)); - CHECK(!ct->get_condition(UF)); + CHECK(i->get_s1() == 50); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "BGT no cond", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = BGT; + s1 = 100, s2 = 50, s3 = 0; + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == -1); delete i; } @@ -693,13 +720,26 @@ TEST_CASE_METHOD(EXFixture, "BGT", "[ex]") InstrDTO *i; m = BGT; + s1 = 100, s2 = 50, s3 = 0; + this->ct->set_condition(GT, true); + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == 50); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "BUF no cond", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = BUF; s1 = 100, s2 = -42027, s3 = 0; - this->ct->set_pc(42096); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); - CHECK(!ct->get_condition(OF)); - CHECK(!ct->get_condition(UF)); + CHECK(i->get_s1() == -1); delete i; } @@ -711,13 +751,26 @@ TEST_CASE_METHOD(EXFixture, "BUF", "[ex]") InstrDTO *i; m = BUF; + s1 = 100, s2 = 50, s3 = 0; + this->ct->set_condition(UF, true); + i = execute_instr(s1, s2, s3, m); + + CHECK(i->get_s1() == 50); + + delete i; +} + +TEST_CASE_METHOD(EXFixture, "BOF no cond", "[ex]") +{ + signed int s1, s2, s3; + Mnemonic m; + InstrDTO *i; + + m = BOF; s1 = 100, s2 = -42027, s3 = 0; - this->ct->set_pc(42096); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); - CHECK(!ct->get_condition(OF)); - CHECK(!ct->get_condition(UF)); + CHECK(i->get_s1() == -1); delete i; } @@ -729,13 +782,11 @@ TEST_CASE_METHOD(EXFixture, "BOF", "[ex]") InstrDTO *i; m = BOF; - s1 = 100, s2 = -42027, s3 = 0; - this->ct->set_pc(42096); + s1 = 100, s2 = 50, s3 = 0; + this->ct->set_condition(OF, true); i = execute_instr(s1, s2, s3, m); - CHECK(i->get_s1() == 69); - CHECK(!ct->get_condition(OF)); - CHECK(!ct->get_condition(UF)); + CHECK(i->get_s1() == 50); delete i; } diff --git a/tests/id.cc b/tests/id.cc index 5270972..77a7cd9 100644 --- a/tests/id.cc +++ b/tests/id.cc @@ -29,9 +29,9 @@ class IDFixture i->set_instr_bits(raw); this->dum->set_curr_instr(i); - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i == nullptr); - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); REQUIRE(i != nullptr); return i; diff --git a/tests/if.cc b/tests/if.cc index 4ebc47d..d6c1bca 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(OK); + r = this->ct->advance(WAIT); // check response CHECK(r == nullptr); } @@ -52,13 +52,13 @@ class IFFixture int i; for (i = 0; i < this->c_delay; ++i) { - r = this->ct->advance(OK); + r = this->ct->advance(WAIT); // check response - CHECK(r == nullptr); + REQUIRE(r == nullptr); } - r = this->ct->advance(OK); + r = this->ct->advance(WAIT); // check response - CHECK(r != nullptr); + REQUIRE(r != nullptr); return r; } @@ -103,8 +103,7 @@ TEST_CASE_METHOD(IFFixture, "fetch returns two instuctions", "[if_pipe]") delete i; } -TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", -"[if_pipe]") +TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", "[if_pipe]") { InstrDTO *i; int j, expected_cycles, fetch_cycles; @@ -115,20 +114,21 @@ TEST_CASE_METHOD(IFFixture, "fetch waits with old instruction", for (j = 0; j < this->m_delay + 1; ++j) { i = this->ct->advance(STALLED); // check response - CHECK(i == nullptr); + REQUIRE(i == nullptr); } for (j = 0; j < this->c_delay; ++j) { i = this->ct->advance(STALLED); // check response - CHECK(i == nullptr); + REQUIRE(i == nullptr); } for (j = 0; j < expected_cycles - fetch_cycles; ++j) { i = this->ct->advance(STALLED); // check response - CHECK(i != nullptr); + REQUIRE(i != nullptr); } - i = this->ct->advance(OK); + i = this->ct->advance(WAIT); + REQUIRE(i != nullptr); CHECK(i->get_time_of(FETCH) == expected_cycles); REQUIRE(i->get_instr_bits() == this->p[0]); |