aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--qtmips_gui/coreview.cpp43
-rw-r--r--qtmips_gui/coreview.h4
-rw-r--r--qtmips_machine/core.cpp67
-rw-r--r--qtmips_machine/core.h5
-rw-r--r--qtmips_machine/tests/testcore.cpp4
5 files changed, 68 insertions, 55 deletions
diff --git a/qtmips_gui/coreview.cpp b/qtmips_gui/coreview.cpp
index 36e9a8d..242c416 100644
--- a/qtmips_gui/coreview.cpp
+++ b/qtmips_gui/coreview.cpp
@@ -268,17 +268,28 @@ QGraphicsSimpleTextItem *CoreViewScene::new_label(const QString &str, qreal x, q
}
CoreViewSceneSimple::CoreViewSceneSimple(machine::QtMipsMachine *machine) : CoreViewScene(machine) {
- NEW_I(instr_prim, 230, 60, instruction_fetched);
+ NEW_I(inst_prim, 230, 60, instruction_executed, QColor(255, 173, 230));
if (machine->config().delay_slot()) {
- NEW(Latch, delay_slot_latch, 55, 470, machine, 25);
- NEW_I(instr_delay, 60, 500, instruction_program_counter);
+ NEW(Latch, latch_if_id, 158, 250, machine, 220);
+ NEW_I(inst_fetch, 79, 60, instruction_fetched, QColor(255, 173, 173));
}
coreview::Connection *con;
// Fetch stage
- new_bus(mem_program->connector_instruction(), dc.instr_bus->new_connector(mem_program->connector_instruction()->point()));
- con = new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), dc.add->connector_in_b());
- con->setAxes({CON_AXIS_Y(270)});
+ if (machine->config().delay_slot()) {
+ struct coreview::Latch::ConnectorPair lp_ft_inst = latch_if_id->new_connector(mem_program->connector_instruction()->y() - latch_if_id->y());
+ new_bus(mem_program->connector_instruction(), lp_ft_inst.in);
+ struct coreview::Latch::ConnectorPair lp_ft_pc = latch_if_id->new_connector(210);
+ new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), lp_ft_pc.in);
+ // Decode stage
+ new_bus(lp_ft_inst.out, dc.instr_bus->new_connector(lp_ft_inst.out->point()));
+ con = new_bus(lp_ft_pc.out, dc.add->connector_in_b());
+ con->setAxes({CON_AXIS_Y(270)});
+ } else {
+ new_bus(mem_program->connector_instruction(), dc.instr_bus->new_connector(mem_program->connector_instruction()->point()));
+ con = new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), dc.add->connector_in_b());
+ con->setAxes({CON_AXIS_Y(270)});
+ }
// Decode stage
coreview::Bus *regs_bus1 = new_bus(regs->connector_read1(), alu->connector_in_a());
const coreview::Connector *regs_bus_con = dc.cmp->new_connector(-0.5, 1);
@@ -301,22 +312,10 @@ CoreViewSceneSimple::CoreViewSceneSimple(machine::QtMipsMachine *machine) : Core
con->setAxes({CON_AXIS_Y(678)});
// WriteBack
// From decode stage to fetch stage
- if (machine->config().delay_slot()) {
- struct coreview::Latch::ConnectorPair lp_addr = delay_slot_latch->new_connector(10);
- struct coreview::Latch::ConnectorPair lp_branch = delay_slot_latch->new_connector(20);
- con = new_signal(dc.and_branch->connector_out(), lp_branch.out);
- con->setAxes({CON_AXIS_Y(370)});
- new_signal(lp_branch.in, ft.multiplex->connector_ctl());
- con = new_bus(dc.add->connector_out(), lp_addr.out);
- con->setAxes({CON_AXIS_Y(360)});
- con = new_bus(lp_addr.in, ft.multiplex->connector_in(1));
- con->setAxes({CON_AXIS_Y(10)});
- } else {
- con = new_signal(dc.and_branch->connector_out(), ft.multiplex->connector_ctl());
- con->setAxes({CON_AXIS_Y(370), CON_AXIS_X(490)});
- con = new_bus(dc.add->connector_out(), ft.multiplex->connector_in(1));
- con->setAxes({CON_AXIS_Y(360), CON_AXIS_X(480), CON_AXIS_Y(10)});
- }
+ con = new_signal(dc.and_branch->connector_out(), ft.multiplex->connector_ctl());
+ con->setAxes({CON_AXIS_Y(370), CON_AXIS_X(490)});
+ con = new_bus(dc.add->connector_out(), ft.multiplex->connector_in(1));
+ con->setAxes({CON_AXIS_Y(360), CON_AXIS_X(480), CON_AXIS_Y(10)});
// From decode to execute stage
new_signal(dc.ctl_block->new_connector(1, 0.6), ex.mux_imm->connector_ctl());
new_signal(dc.ctl_block->new_connector(1, 0.2), alu->connector_ctl());
diff --git a/qtmips_gui/coreview.h b/qtmips_gui/coreview.h
index 0abc870..93c0032 100644
--- a/qtmips_gui/coreview.h
+++ b/qtmips_gui/coreview.h
@@ -130,8 +130,8 @@ public:
CoreViewSceneSimple(machine::QtMipsMachine *machine);
private:
- coreview::InstructionView *instr_prim, *instr_delay;
- coreview::Latch *delay_slot_latch;
+ coreview::InstructionView *inst_prim, *inst_fetch;
+ coreview::Latch *latch_if_id;
};
class CoreViewScenePipelined : public CoreViewScene {
diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp
index 64c309b..187ca2f 100644
--- a/qtmips_machine/core.cpp
+++ b/qtmips_machine/core.cpp
@@ -554,7 +554,7 @@ void Core::writeback(const struct dtMemory &dt) {
regs->write_gp(dt.rwrite, dt.towrite_val);
}
-bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) {
+bool Core::handle_pc(const struct dtDecode &dt) {
bool branch = false;
emit instruction_program_counter(dt.inst, dt.inst_addr, EXCAUSE_NONE);
@@ -593,7 +593,7 @@ bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) {
std::int32_t rel_offset = dt.inst.immediate() << 2;
if (rel_offset & (1 << 17))
rel_offset -= 1 << 18;
- regs->pc_jmp(rel_offset + rel_adj);
+ regs->pc_abs_jmp(dt.inst_addr + rel_offset + 4);
} else {
regs->pc_inc();
}
@@ -672,57 +672,66 @@ CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess
bool jmp_delay_slot, unsigned int min_cache_row_size, Cop0State *cop0state) :
Core(regs, mem_program, mem_data, min_cache_row_size, cop0state) {
if (jmp_delay_slot)
- jmp_delay_decode = new struct Core::dtDecode();
+ dt_f = new struct Core::dtFetch();
else
- jmp_delay_decode = nullptr;
+ dt_f = nullptr;
reset();
}
CoreSingle::~CoreSingle() {
- if (jmp_delay_decode != nullptr)
- delete jmp_delay_decode;
+ if (dt_f != nullptr)
+ delete dt_f;
}
void CoreSingle::do_step(bool skip_break) {
- bool in_delay_slot = false;
- std::uint32_t jump_branch_pc;
+ bool branch_taken = false;
struct dtFetch f = fetch(skip_break);
+ if (dt_f != nullptr) {
+ struct dtFetch f_swap = *dt_f;
+ *dt_f = f;
+ f = f_swap;
+ }
struct dtDecode d = decode(f);
+ struct dtExecute e = execute(d);
+ struct dtMemory m = memory(e);
+ writeback(m);
// Handle PC before instruction following jump leaves decode stage
- if (jmp_delay_decode != nullptr) {
- in_delay_slot = handle_pc(*jmp_delay_decode);
- if (jmp_delay_decode->nb_skip_ds && !in_delay_slot) {
- // Discard processing of instruction in delay slot
- // for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL
- dtDecodeInit(d);
- }
- jump_branch_pc = jmp_delay_decode->inst_addr;
- *jmp_delay_decode = d; // Copy current decode
+
+ if ((m.stop_if || (m.excause != EXCAUSE_NONE)) && dt_f != nullptr) {
+ dtFetchInit(*dt_f);
+ emit instruction_fetched(dt_f->inst, dt_f->inst_addr, dt_f->excause);
+ emit fetch_inst_addr_value(STAGEADDR_NONE);
} else {
- handle_pc(d, 4);
- jump_branch_pc = d.inst_addr;
+ branch_taken = handle_pc(d);
+ if (dt_f != nullptr) {
+ dt_f->in_delay_slot = branch_taken;
+ if (d.nb_skip_ds && !branch_taken) {
+ // Discard processing of instruction in delay slot
+ // for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL
+ dtFetchInit(*dt_f);
+ }
+ }
}
- struct dtExecute e = execute(d);
- struct dtMemory m = memory(e);
- writeback(m);
-
if (m.excause != EXCAUSE_NONE) {
- if (jmp_delay_decode != nullptr)
- dtDecodeInit(*jmp_delay_decode);
+ if (dt_f != nullptr) {
+ regs->pc_abs_jmp(dt_f->inst_addr);
+ }
handle_exception(this, regs, m.excause, m.inst_addr, regs->read_pc(),
- jump_branch_pc, in_delay_slot, m.mem_addr);
+ prev_inst_addr, m.in_delay_slot, m.mem_addr);
return;
}
+ prev_inst_addr = m.inst_addr;
}
void CoreSingle::do_reset() {
- if (jmp_delay_decode != nullptr) {
- Core::dtDecodeInit(*jmp_delay_decode);
- jmp_delay_decode->inst_addr = 0;
+ if (dt_f != nullptr) {
+ Core::dtFetchInit(*dt_f);
+ dt_f->inst_addr = 0;
}
+ prev_inst_addr = 0;
}
CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data,
diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h
index 5658726..6b025db 100644
--- a/qtmips_machine/core.h
+++ b/qtmips_machine/core.h
@@ -259,7 +259,7 @@ protected:
struct dtExecute execute(const struct dtDecode&);
struct dtMemory memory(const struct dtExecute&);
void writeback(const struct dtMemory&);
- bool handle_pc(const struct dtDecode&, std::int32_t rel_adj = 0);
+ bool handle_pc(const struct dtDecode&);
enum ExceptionCause memory_special(enum AccessControl memctl,
int mode, bool memread, bool memwrite,
@@ -298,7 +298,8 @@ protected:
void do_reset();
private:
- struct Core::dtDecode *jmp_delay_decode;
+ struct Core::dtFetch *dt_f;
+ std::uint32_t prev_inst_addr;
};
class CorePipelined : public Core {
diff --git a/qtmips_machine/tests/testcore.cpp b/qtmips_machine/tests/testcore.cpp
index 68da14c..7ba185d 100644
--- a/qtmips_machine/tests/testcore.cpp
+++ b/qtmips_machine/tests/testcore.cpp
@@ -230,7 +230,9 @@ void MachineTests::singlecore_regs() {
CoreSingle core(&init, &mem_used, &mem_used, true);
core.step(); // Single step should be enought as this is risc without pipeline
+ core.step();
+ res.pc_inc();
res.pc_inc(); // We did single step so increment program counter accordingly
QCOMPARE(init, res); // After doing changes from initial state this should be same state as in case of passed expected result
QCOMPARE(mem, mem_used); // There should be no change in memory
@@ -444,8 +446,10 @@ void MachineTests::singlecore_mem() {
CoreSingle core(&regs_init, &mem_init, &mem_init, true);
core.step();
+ core.step();
regs_res.pc_inc();
+ regs_res.pc_inc();
QCOMPARE(regs_init, regs_res);
QCOMPARE(mem_init, mem_res);
}