summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--inc/id.h3
-rw-r--r--inc/instr.h7
-rw-r--r--inc/instrDTO.h14
-rw-r--r--inc/stage.h9
-rw-r--r--src/sim/controller.cc5
-rw-r--r--src/sim/ex.cc8
-rw-r--r--src/sim/id.cc13
-rw-r--r--src/sim/instrDTO.cc7
-rw-r--r--src/sim/mm.cc22
-rw-r--r--src/sim/stage.cc10
-rw-r--r--src/sim/wb.cc32
11 files changed, 111 insertions, 19 deletions
diff --git a/inc/id.h b/inc/id.h
index 3ff5063..ebbe290 100644
--- a/inc/id.h
+++ b/inc/id.h
@@ -64,8 +64,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);
+ 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);
diff --git a/inc/instr.h b/inc/instr.h
index 7fbb42b..d17613d 100644
--- a/inc/instr.h
+++ b/inc/instr.h
@@ -45,6 +45,13 @@ 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 77a223e..8249122 100644
--- a/inc/instrDTO.h
+++ b/inc/instrDTO.h
@@ -43,6 +43,10 @@ class InstrDTO
* @return the mnemonic of the instruction
*/
Mnemonic get_mnemonic();
+ /**
+ * @return the type of the instruction
+ */
+ Type get_type();
/**
* @param set hist key
@@ -68,6 +72,11 @@ class InstrDTO
* @param the mnemonic of the instruction
*/
void set_mnemonic(Mnemonic);
+
+ /**
+ * @param the type of the instruction
+ */
+ void set_type(Type);
private:
/**
@@ -91,6 +100,11 @@ class InstrDTO
* The mnemonic of the operation.
*/
Mnemonic mnemonic;
+
+ /**
+ * Type of the instruction
+ */
+ Type type;
};
#endif /* INSTRDTO_H_INCLUDED */
diff --git a/inc/stage.h b/inc/stage.h
index 84d2a7b..03048b0 100644
--- a/inc/stage.h
+++ b/inc/stage.h
@@ -30,11 +30,9 @@ class Stage
* Advances this stage by a single clock cycle.
* A boilerplate version is provided in stage.cc.
*
- * @param a DTO object containing the next instruction to be processed.
* @param a response, indicating whether or not the parent pipe stage is
* ready to accept a new instruction object next cycle.
- * @return a response, indicating whether this pipeline stage is stalling,
- * busy, or done.
+ * @return a DTO object containing the next instruction to be processed.
*
* Must set the status to STALLED when an operation completes.
*/
@@ -55,6 +53,11 @@ class Stage
*/
void set_pc(unsigned int pc);
+ /**
+ * Squashes the pipeline.
+ */
+ void squash();
+
protected:
/**
* The function expected to do the majority of the work.
diff --git a/src/sim/controller.cc b/src/sim/controller.cc
index 06591af..89ff4e7 100644
--- a/src/sim/controller.cc
+++ b/src/sim/controller.cc
@@ -31,10 +31,11 @@ int Controller::get_pc() { return this->pc; }
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/ex.cc b/src/sim/ex.cc
index 95cce8d..f22adc0 100644
--- a/src/sim/ex.cc
+++ b/src/sim/ex.cc
@@ -282,28 +282,28 @@ EX::EX(Stage *stage) : Stage(stage)
INIT_INSTRUCTION(
BEQ,
{
- s1 = this->pc + s2;
+ (this->get_condition(EQ)) ? s1 = this->pc + s2 : s1 = this->pc;
(void)s3;
}),
INIT_INSTRUCTION(
BGT,
{
- s1 = this->pc + s2;
+ (this->get_condition(GT)) ? s1 = this->pc + s2 : s1 = this->pc;
(void)s3;
}),
INIT_INSTRUCTION(
BUF,
{
- s1 = this->pc + s2;
+ (this->get_condition(UF)) ? s1 = this->pc + s2 : s1 = this->pc;
(void)s3;
}),
INIT_INSTRUCTION(
BOF,
{
- s1 = this->pc + s2;
+ (this->get_condition(OF)) ? s1 = this->pc + s2 : s1 = this->pc;
(void)s3;
}),
diff --git a/src/sim/id.cc b/src/sim/id.cc
index edf74e2..0b75b64 100644
--- a/src/sim/id.cc
+++ b/src/sim/id.cc
@@ -46,38 +46,43 @@ void ID::advance_helper()
{
signed int s1, s2, s3;
Mnemonic m;
+ Type t;
// it may be good to ensure we are not doing
// work that has already been done
- if (this->curr_instr) {
+ if (this->curr_instr && this->curr_instr->get_mnemonic() == NONE) {
s1 = curr_instr->get_instr_bits();
- get_instr_fields(s1, s2, s3, m);
+ 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)
+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);
break;
case 0b01:
+ t = I;
this->decode_I_type(s1, s2, s3);
break;
case 0b10:
+ t = J;
this->decode_J_type(s1, s2);
break;
case 0b11:
+ t = INV;
this->status = OK;
}
}
diff --git a/src/sim/instrDTO.cc b/src/sim/instrDTO.cc
index 5a7fe3b..b33c26b 100644
--- a/src/sim/instrDTO.cc
+++ b/src/sim/instrDTO.cc
@@ -7,7 +7,8 @@ InstrDTO::InstrDTO()
this->s1 = 0;
this->s2 = 0;
this->s3 = 0;
- this->mnemonic = NOP;
+ this->mnemonic = NONE;
+ this->type = INV;
}
int InstrDTO::get_time_of(Accessor a) { return this->hist[a]; }
@@ -22,6 +23,8 @@ signed int InstrDTO::get_s3() { return this->s3; }
Mnemonic InstrDTO::get_mnemonic() { return this->mnemonic; }
+Type InstrDTO::get_type() { return this->type; }
+
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; }
@@ -33,3 +36,5 @@ 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; }
diff --git a/src/sim/mm.cc b/src/sim/mm.cc
index 2b73207..cd85056 100644
--- a/src/sim/mm.cc
+++ b/src/sim/mm.cc
@@ -6,4 +6,24 @@
MM::MM(Stage *stage) : Stage(stage) { this->id = MEM; }
-void MM::advance_helper() {}
+void MM::advance_helper() {
+ Response r;
+ 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;
+ }
+ }
+}
diff --git a/src/sim/stage.cc b/src/sim/stage.cc
index 5b81e4c..be69d77 100644
--- a/src/sim/stage.cc
+++ b/src/sim/stage.cc
@@ -35,7 +35,7 @@ InstrDTO *Stage::advance(Response p)
Response n;
this->advance_helper();
- if (this->curr_instr != nullptr && p == OK) {
+ if (this->status == OK && this->curr_instr != nullptr && p == OK) {
// mutual consent
this->curr_instr->set_time_of(this->id, this->clock_cycle);
r = new InstrDTO(*this->curr_instr);
@@ -78,3 +78,11 @@ 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){
+ this->next->squash();
+ }
+}
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index 9337aa0..ac47f25 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -6,4 +6,34 @@
WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; }
-void WB::advance_helper() {}
+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;
+}