summaryrefslogtreecommitdiff
path: root/src/sim/wb.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/wb.cc')
-rw-r--r--src/sim/wb.cc75
1 files changed, 48 insertions, 27 deletions
diff --git a/src/sim/wb.cc b/src/sim/wb.cc
index 276d1d0..01768e8 100644
--- a/src/sim/wb.cc
+++ b/src/sim/wb.cc
@@ -8,33 +8,54 @@ WB::WB(Stage *stage) : Stage(stage) { this->id = WRITE; }
void WB::advance_helper()
{
- 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();
- }
+ 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);
+}