Skip to content

Commit c72e3ad

Browse files
committed
Change single cycle core with delay slot to use separate fetch stage.
When instructions are visualized then it is even more misleading to keep old instruction in decode phase delay buffer. The single cycle core with delay slot is upgraded to the variant with fetch and execute phases. This way the structure is logical and delay slot has purpose. Signed-off-by: Pavel Pisa <[email protected]>
1 parent 816b01b commit c72e3ad

File tree

5 files changed

+68
-55
lines changed

5 files changed

+68
-55
lines changed

qtmips_gui/coreview.cpp

+21-22
Original file line numberDiff line numberDiff line change
@@ -268,17 +268,28 @@ QGraphicsSimpleTextItem *CoreViewScene::new_label(const QString &str, qreal x, q
268268
}
269269

270270
CoreViewSceneSimple::CoreViewSceneSimple(machine::QtMipsMachine *machine) : CoreViewScene(machine) {
271-
NEW_I(instr_prim, 230, 60, instruction_fetched);
271+
NEW_I(inst_prim, 230, 60, instruction_executed, QColor(255, 173, 230));
272272
if (machine->config().delay_slot()) {
273-
NEW(Latch, delay_slot_latch, 55, 470, machine, 25);
274-
NEW_I(instr_delay, 60, 500, instruction_program_counter);
273+
NEW(Latch, latch_if_id, 158, 250, machine, 220);
274+
NEW_I(inst_fetch, 79, 60, instruction_fetched, QColor(255, 173, 173));
275275
}
276276

277277
coreview::Connection *con;
278278
// Fetch stage
279-
new_bus(mem_program->connector_instruction(), dc.instr_bus->new_connector(mem_program->connector_instruction()->point()));
280-
con = new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), dc.add->connector_in_b());
281-
con->setAxes({CON_AXIS_Y(270)});
279+
if (machine->config().delay_slot()) {
280+
struct coreview::Latch::ConnectorPair lp_ft_inst = latch_if_id->new_connector(mem_program->connector_instruction()->y() - latch_if_id->y());
281+
new_bus(mem_program->connector_instruction(), lp_ft_inst.in);
282+
struct coreview::Latch::ConnectorPair lp_ft_pc = latch_if_id->new_connector(210);
283+
new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), lp_ft_pc.in);
284+
// Decode stage
285+
new_bus(lp_ft_inst.out, dc.instr_bus->new_connector(lp_ft_inst.out->point()));
286+
con = new_bus(lp_ft_pc.out, dc.add->connector_in_b());
287+
con->setAxes({CON_AXIS_Y(270)});
288+
} else {
289+
new_bus(mem_program->connector_instruction(), dc.instr_bus->new_connector(mem_program->connector_instruction()->point()));
290+
con = new_bus(ft.junc_pc_4->new_connector(coreview::Connector::AX_Y), dc.add->connector_in_b());
291+
con->setAxes({CON_AXIS_Y(270)});
292+
}
282293
// Decode stage
283294
coreview::Bus *regs_bus1 = new_bus(regs->connector_read1(), alu->connector_in_a());
284295
const coreview::Connector *regs_bus_con = dc.cmp->new_connector(-0.5, 1);
@@ -301,22 +312,10 @@ CoreViewSceneSimple::CoreViewSceneSimple(machine::QtMipsMachine *machine) : Core
301312
con->setAxes({CON_AXIS_Y(678)});
302313
// WriteBack
303314
// From decode stage to fetch stage
304-
if (machine->config().delay_slot()) {
305-
struct coreview::Latch::ConnectorPair lp_addr = delay_slot_latch->new_connector(10);
306-
struct coreview::Latch::ConnectorPair lp_branch = delay_slot_latch->new_connector(20);
307-
con = new_signal(dc.and_branch->connector_out(), lp_branch.out);
308-
con->setAxes({CON_AXIS_Y(370)});
309-
new_signal(lp_branch.in, ft.multiplex->connector_ctl());
310-
con = new_bus(dc.add->connector_out(), lp_addr.out);
311-
con->setAxes({CON_AXIS_Y(360)});
312-
con = new_bus(lp_addr.in, ft.multiplex->connector_in(1));
313-
con->setAxes({CON_AXIS_Y(10)});
314-
} else {
315-
con = new_signal(dc.and_branch->connector_out(), ft.multiplex->connector_ctl());
316-
con->setAxes({CON_AXIS_Y(370), CON_AXIS_X(490)});
317-
con = new_bus(dc.add->connector_out(), ft.multiplex->connector_in(1));
318-
con->setAxes({CON_AXIS_Y(360), CON_AXIS_X(480), CON_AXIS_Y(10)});
319-
}
315+
con = new_signal(dc.and_branch->connector_out(), ft.multiplex->connector_ctl());
316+
con->setAxes({CON_AXIS_Y(370), CON_AXIS_X(490)});
317+
con = new_bus(dc.add->connector_out(), ft.multiplex->connector_in(1));
318+
con->setAxes({CON_AXIS_Y(360), CON_AXIS_X(480), CON_AXIS_Y(10)});
320319
// From decode to execute stage
321320
new_signal(dc.ctl_block->new_connector(1, 0.6), ex.mux_imm->connector_ctl());
322321
new_signal(dc.ctl_block->new_connector(1, 0.2), alu->connector_ctl());

qtmips_gui/coreview.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ class CoreViewSceneSimple : public CoreViewScene {
130130
CoreViewSceneSimple(machine::QtMipsMachine *machine);
131131

132132
private:
133-
coreview::InstructionView *instr_prim, *instr_delay;
134-
coreview::Latch *delay_slot_latch;
133+
coreview::InstructionView *inst_prim, *inst_fetch;
134+
coreview::Latch *latch_if_id;
135135
};
136136

137137
class CoreViewScenePipelined : public CoreViewScene {

qtmips_machine/core.cpp

+38-29
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ void Core::writeback(const struct dtMemory &dt) {
554554
regs->write_gp(dt.rwrite, dt.towrite_val);
555555
}
556556

557-
bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) {
557+
bool Core::handle_pc(const struct dtDecode &dt) {
558558
bool branch = false;
559559
emit instruction_program_counter(dt.inst, dt.inst_addr, EXCAUSE_NONE);
560560

@@ -593,7 +593,7 @@ bool Core::handle_pc(const struct dtDecode &dt, int32_t rel_adj) {
593593
std::int32_t rel_offset = dt.inst.immediate() << 2;
594594
if (rel_offset & (1 << 17))
595595
rel_offset -= 1 << 18;
596-
regs->pc_jmp(rel_offset + rel_adj);
596+
regs->pc_abs_jmp(dt.inst_addr + rel_offset + 4);
597597
} else {
598598
regs->pc_inc();
599599
}
@@ -672,57 +672,66 @@ CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess
672672
bool jmp_delay_slot, unsigned int min_cache_row_size, Cop0State *cop0state) :
673673
Core(regs, mem_program, mem_data, min_cache_row_size, cop0state) {
674674
if (jmp_delay_slot)
675-
jmp_delay_decode = new struct Core::dtDecode();
675+
dt_f = new struct Core::dtFetch();
676676
else
677-
jmp_delay_decode = nullptr;
677+
dt_f = nullptr;
678678
reset();
679679
}
680680

681681
CoreSingle::~CoreSingle() {
682-
if (jmp_delay_decode != nullptr)
683-
delete jmp_delay_decode;
682+
if (dt_f != nullptr)
683+
delete dt_f;
684684
}
685685

686686
void CoreSingle::do_step(bool skip_break) {
687-
bool in_delay_slot = false;
688-
std::uint32_t jump_branch_pc;
687+
bool branch_taken = false;
689688

690689
struct dtFetch f = fetch(skip_break);
690+
if (dt_f != nullptr) {
691+
struct dtFetch f_swap = *dt_f;
692+
*dt_f = f;
693+
f = f_swap;
694+
}
691695
struct dtDecode d = decode(f);
696+
struct dtExecute e = execute(d);
697+
struct dtMemory m = memory(e);
698+
writeback(m);
692699

693700
// Handle PC before instruction following jump leaves decode stage
694-
if (jmp_delay_decode != nullptr) {
695-
in_delay_slot = handle_pc(*jmp_delay_decode);
696-
if (jmp_delay_decode->nb_skip_ds && !in_delay_slot) {
697-
// Discard processing of instruction in delay slot
698-
// for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL
699-
dtDecodeInit(d);
700-
}
701-
jump_branch_pc = jmp_delay_decode->inst_addr;
702-
*jmp_delay_decode = d; // Copy current decode
701+
702+
if ((m.stop_if || (m.excause != EXCAUSE_NONE)) && dt_f != nullptr) {
703+
dtFetchInit(*dt_f);
704+
emit instruction_fetched(dt_f->inst, dt_f->inst_addr, dt_f->excause);
705+
emit fetch_inst_addr_value(STAGEADDR_NONE);
703706
} else {
704-
handle_pc(d, 4);
705-
jump_branch_pc = d.inst_addr;
707+
branch_taken = handle_pc(d);
708+
if (dt_f != nullptr) {
709+
dt_f->in_delay_slot = branch_taken;
710+
if (d.nb_skip_ds && !branch_taken) {
711+
// Discard processing of instruction in delay slot
712+
// for BEQL, BNEL, BLEZL, BGTZL, BLTZL, BGEZL, BLTZALL, BGEZALL
713+
dtFetchInit(*dt_f);
714+
}
715+
}
706716
}
707717

708-
struct dtExecute e = execute(d);
709-
struct dtMemory m = memory(e);
710-
writeback(m);
711-
712718
if (m.excause != EXCAUSE_NONE) {
713-
if (jmp_delay_decode != nullptr)
714-
dtDecodeInit(*jmp_delay_decode);
719+
if (dt_f != nullptr) {
720+
regs->pc_abs_jmp(dt_f->inst_addr);
721+
}
715722
handle_exception(this, regs, m.excause, m.inst_addr, regs->read_pc(),
716-
jump_branch_pc, in_delay_slot, m.mem_addr);
723+
prev_inst_addr, m.in_delay_slot, m.mem_addr);
717724
return;
718725
}
726+
prev_inst_addr = m.inst_addr;
719727
}
720728

721729
void CoreSingle::do_reset() {
722-
if (jmp_delay_decode != nullptr) {
723-
Core::dtDecodeInit(*jmp_delay_decode);
724-
jmp_delay_decode->inst_addr = 0;
730+
if (dt_f != nullptr) {
731+
Core::dtFetchInit(*dt_f);
732+
dt_f->inst_addr = 0;
725733
}
734+
prev_inst_addr = 0;
726735
}
727736

728737
CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data,

qtmips_machine/core.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ class Core : public QObject {
259259
struct dtExecute execute(const struct dtDecode&);
260260
struct dtMemory memory(const struct dtExecute&);
261261
void writeback(const struct dtMemory&);
262-
bool handle_pc(const struct dtDecode&, std::int32_t rel_adj = 0);
262+
bool handle_pc(const struct dtDecode&);
263263

264264
enum ExceptionCause memory_special(enum AccessControl memctl,
265265
int mode, bool memread, bool memwrite,
@@ -298,7 +298,8 @@ class CoreSingle : public Core {
298298
void do_reset();
299299

300300
private:
301-
struct Core::dtDecode *jmp_delay_decode;
301+
struct Core::dtFetch *dt_f;
302+
std::uint32_t prev_inst_addr;
302303
};
303304

304305
class CorePipelined : public Core {

qtmips_machine/tests/testcore.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,9 @@ void MachineTests::singlecore_regs() {
230230

231231
CoreSingle core(&init, &mem_used, &mem_used, true);
232232
core.step(); // Single step should be enought as this is risc without pipeline
233+
core.step();
233234

235+
res.pc_inc();
234236
res.pc_inc(); // We did single step so increment program counter accordingly
235237
QCOMPARE(init, res); // After doing changes from initial state this should be same state as in case of passed expected result
236238
QCOMPARE(mem, mem_used); // There should be no change in memory
@@ -444,7 +446,9 @@ void MachineTests::singlecore_mem() {
444446

445447
CoreSingle core(&regs_init, &mem_init, &mem_init, true);
446448
core.step();
449+
core.step();
447450

451+
regs_res.pc_inc();
448452
regs_res.pc_inc();
449453
QCOMPARE(regs_init, regs_res);
450454
QCOMPARE(mem_init, mem_res);

0 commit comments

Comments
 (0)