summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/ex.h2
-rw-r--r--inc/id.h4
-rw-r--r--inc/instr.h8
-rw-r--r--inc/instrDTO.h15
-rw-r--r--inc/stage.h35
-rw-r--r--inc/wb.h20
-rw-r--r--src/sim/controller.cc5
-rw-r--r--src/sim/dum.cc8
-rw-r--r--src/sim/ex.cc70
-rw-r--r--src/sim/id.cc30
-rw-r--r--src/sim/if.cc5
-rw-r--r--src/sim/instrDTO.cc7
-rw-r--r--src/sim/mm.cc44
-rw-r--r--src/sim/stage.cc53
-rw-r--r--src/sim/wb.cc82
-rw-r--r--tests/controller.cc334
-rw-r--r--tests/ex.cc95
-rw-r--r--tests/id.cc4
-rw-r--r--tests/if.cc22
19 files changed, 650 insertions, 193 deletions
diff --git a/inc/ex.h b/inc/ex.h
index 6d4254e..e4c9d2b 100644
--- a/inc/ex.h
+++ b/inc/ex.h
@@ -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;
};
diff --git a/inc/id.h b/inc/id.h
index ebbe290..fd8c874 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -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.
*/
diff --git a/inc/wb.h b/inc/wb.h
index 62cef17..c4755ea 100644
--- a/inc/wb.h
+++ b/inc/wb.h
@@ -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..cf8d02d 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;
@@ -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..0df26f4 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;
@@ -106,9 +107,11 @@ void ID::decode_R_type(signed int &s1, signed int &s2, signed int &s3)
this->status = (r1 == OK && r2 == OK) ? OK : STALLED;
}
-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 +120,21 @@ 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;
+ 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..24bdf75 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,30 @@ 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) {
+ 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 +70,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..c7e3c93 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,316 @@ 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);
+ 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);
- 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() == 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() == b);
+ 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);
+
+ 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);
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]);