From 635567e0564db4d19741b2478a4129fccb76f64a Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Mon, 25 Mar 2019 23:13:31 +0100 Subject: Highlight instructions passing through the pipeline stages. Signed-off-by: Pavel Pisa --- qtmips_gui/programdock.cpp | 22 +++++++++++++++++----- qtmips_gui/programdock.h | 1 + qtmips_gui/programmodel.cpp | 37 ++++++++++++++++++++++++++++++++++++- qtmips_gui/programmodel.h | 12 ++++++++++++ qtmips_machine/core.cpp | 20 ++++++++++++++++---- qtmips_machine/core.h | 4 ++++ qtmips_machine/machinedefs.h | 2 ++ 7 files changed, 88 insertions(+), 10 deletions(-) diff --git a/qtmips_gui/programdock.cpp b/qtmips_gui/programdock.cpp index 60a23b0..f3d3d78 100644 --- a/qtmips_gui/programdock.cpp +++ b/qtmips_gui/programdock.cpp @@ -101,6 +101,8 @@ ProgramDock::ProgramDock(QWidget *parent, QSettings *settings) : Super(parent) { program_content, SLOT(focus_address_with_save(std::uint32_t))); connect(program_content, SIGNAL(doubleClicked(QModelIndex)), program_model, SLOT(toggle_hw_break(QModelIndex))); + connect(this, SIGNAL(stage_addr_changed(uint,std::uint32_t)), + program_model, SLOT(update_stage_addr(uint,std::uint32_t))); } void ProgramDock::setup(machine::QtMipsMachine *machine) { @@ -121,31 +123,41 @@ void ProgramDock::set_follow_inst(int follow) { } void ProgramDock::fetch_inst_addr(std::uint32_t addr) { - follow_addr[FOLLOWSRC_FETCH] = addr; + if (addr != machine::STAGEADDR_NONE) + follow_addr[FOLLOWSRC_FETCH] = addr; + emit stage_addr_changed(ProgramModel::STAGEADDR_FETCH, addr); if (follow_source == FOLLOWSRC_FETCH) update_follow_position(); } void ProgramDock::decode_inst_addr(std::uint32_t addr) { - follow_addr[FOLLOWSRC_DECODE] = addr; + if (addr != machine::STAGEADDR_NONE) + follow_addr[FOLLOWSRC_DECODE] = addr; + emit stage_addr_changed(ProgramModel::STAGEADDR_DECODE, addr); if (follow_source == FOLLOWSRC_DECODE) update_follow_position(); } void ProgramDock::execute_inst_addr(std::uint32_t addr) { - follow_addr[FOLLOWSRC_EXECUTE] = addr; + if (addr != machine::STAGEADDR_NONE) + follow_addr[FOLLOWSRC_EXECUTE] = addr; + emit stage_addr_changed(ProgramModel::STAGEADDR_EXECUTE, addr); if (follow_source == FOLLOWSRC_EXECUTE) update_follow_position(); } void ProgramDock::memory_inst_addr(std::uint32_t addr) { - follow_addr[FOLLOWSRC_MEMORY] = addr; + if (addr != machine::STAGEADDR_NONE) + follow_addr[FOLLOWSRC_MEMORY] = addr; + emit stage_addr_changed(ProgramModel::STAGEADDR_MEMORY, addr); if (follow_source == FOLLOWSRC_MEMORY) update_follow_position(); } void ProgramDock::writeback_inst_addr(std::uint32_t addr) { - follow_addr[FOLLOWSRC_WRITEBACK] = addr; + if (addr != machine::STAGEADDR_NONE) + follow_addr[FOLLOWSRC_WRITEBACK] = addr; + emit stage_addr_changed(ProgramModel::STAGEADDR_WRITEBACK, addr); if (follow_source == FOLLOWSRC_WRITEBACK) update_follow_position(); } diff --git a/qtmips_gui/programdock.h b/qtmips_gui/programdock.h index 356666f..0dec65d 100644 --- a/qtmips_gui/programdock.h +++ b/qtmips_gui/programdock.h @@ -57,6 +57,7 @@ signals: void jump_to_pc(std::uint32_t); void focus_addr(std::uint32_t); void focus_addr_with_save(std::uint32_t); + void stage_addr_changed(uint stage, std::uint32_t addr); public slots: void set_follow_inst(int); void fetch_inst_addr(std::uint32_t addr); diff --git a/qtmips_gui/programmodel.cpp b/qtmips_gui/programmodel.cpp index 838c058..6fda037 100644 --- a/qtmips_gui/programmodel.cpp +++ b/qtmips_gui/programmodel.cpp @@ -44,6 +44,9 @@ ProgramModel::ProgramModel(QObject *parent) machine = nullptr; memory_change_counter = 0; cache_program_change_counter = 0; + for (int i = 0 ; i < STAGEADDR_COUNT; i++) + stage_addr[i] = machine::STAGEADDR_NONE; + stages_need_update = false; } int ProgramModel::rowCount(const QModelIndex & /*parent*/) const { @@ -125,6 +128,26 @@ QVariant ProgramModel::data(const QModelIndex &index, int role) const { } else if (index.column() == 0 && machine->is_hwbreak(address)) { QBrush bgd(Qt::red); return bgd; + } else if (index.column() == 3) { + if (address == stage_addr[STAGEADDR_WRITEBACK]) { + QBrush bgd(QColor(255, 173, 230)); + return bgd; + } else if (address == stage_addr[STAGEADDR_MEMORY]) { + QBrush bgd(QColor(173, 255, 229)); + return bgd; + } else if (address == stage_addr[STAGEADDR_MEMORY]) { + QBrush bgd(QColor(173, 255, 229)); + return bgd; + } else if (address == stage_addr[STAGEADDR_EXECUTE]) { + QBrush bgd(QColor(193, 255, 173)); + return bgd; + } else if (address == stage_addr[STAGEADDR_DECODE]) { + QBrush bgd(QColor(255, 212, 173)); + return bgd; + } else if (address == stage_addr[STAGEADDR_FETCH]) { + QBrush bgd(QColor(255, 173, 173)); + return bgd; + } } return QVariant(); } @@ -135,6 +158,8 @@ QVariant ProgramModel::data(const QModelIndex &index, int role) const { void ProgramModel::setup(machine::QtMipsMachine *machine) { this->machine = machine; + for (int i = 0 ; i < STAGEADDR_COUNT; i++) + stage_addr[i] = machine::STAGEADDR_NONE; if (machine != nullptr) connect(machine, SIGNAL(post_tick()), this, SLOT(check_for_updates())); emit update_all(); @@ -146,11 +171,12 @@ void ProgramModel::update_all() { if (machine->cache_program() != nullptr) cache_program_change_counter = machine->cache_program()->get_change_counter(); } + stages_need_update = false; emit dataChanged(index(0, 0), index(rowCount() - 1, columnCount() - 1)); } void ProgramModel::check_for_updates() { - bool need_update = false; + bool need_update = stages_need_update; if (machine == nullptr) return; if (machine->memory() == nullptr) @@ -240,3 +266,12 @@ bool ProgramModel::setData(const QModelIndex & index, const QVariant & value, in } return true; } + +void ProgramModel::update_stage_addr(uint stage, std::uint32_t addr) { + if (stage < STAGEADDR_COUNT) { + if (stage_addr[stage] != addr) { + stage_addr[stage] = addr; + stages_need_update = true; + } + } +} diff --git a/qtmips_gui/programmodel.h b/qtmips_gui/programmodel.h index f5159af..a7c1699 100644 --- a/qtmips_gui/programmodel.h +++ b/qtmips_gui/programmodel.h @@ -84,10 +84,20 @@ public: return true; } + enum StageAddress { + STAGEADDR_FETCH, + STAGEADDR_DECODE, + STAGEADDR_EXECUTE, + STAGEADDR_MEMORY, + STAGEADDR_WRITEBACK, + STAGEADDR_COUNT, + }; + public slots: void setup(machine::QtMipsMachine *machine); void check_for_updates(); void toggle_hw_break(const QModelIndex & index); + void update_stage_addr(uint stage, std::uint32_t addr); private: std::uint32_t index0_offset; @@ -95,6 +105,8 @@ private: machine::QtMipsMachine *machine; std::uint32_t memory_change_counter; std::uint32_t cache_program_change_counter; + std::uint32_t stage_addr[STAGEADDR_COUNT]; + bool stages_need_update; }; #endif // PROGRAMMODEL_H diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 45b08ec..64c309b 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -275,6 +275,7 @@ struct Core::dtFetch Core::fetch(bool skip_break) { .inst_addr = inst_addr, .excause = excause, .in_delay_slot = false, + .is_valid = true, }; } @@ -316,7 +317,7 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) { excause = dt.inst.encoded_exception(); } - emit decode_inst_addr_value(dt.inst_addr); + emit decode_inst_addr_value(dt.is_valid? dt.inst_addr: STAGEADDR_NONE); emit instruction_decoded(dt.inst, dt.inst_addr, excause); emit decode_instruction_value(dt.inst.data()); emit decode_reg1_value(val_rs); @@ -374,6 +375,7 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) { .in_delay_slot = dt.in_delay_slot, .stall = false, .stop_if = !!(flags & IMF_STOP_IF), + .is_valid = dt.is_valid, }; } @@ -447,7 +449,7 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { } } - emit execute_inst_addr_value(dt.inst_addr); + emit execute_inst_addr_value(dt.is_valid? dt.inst_addr: STAGEADDR_NONE); emit instruction_executed(dt.inst, dt.inst_addr, excause); emit execute_alu_value(alu_val); emit execute_reg1_value(dt.val_rs); @@ -485,6 +487,7 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { .excause = excause, .in_delay_slot = dt.in_delay_slot, .stop_if = dt.stop_if, + .is_valid = dt.is_valid, }; } @@ -514,7 +517,7 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { regwrite = false; } - emit memory_inst_addr_value(dt.inst_addr); + emit memory_inst_addr_value(dt.is_valid? dt.inst_addr: STAGEADDR_NONE); emit instruction_memory(dt.inst, dt.inst_addr, dt.excause); emit memory_alu_value(dt.alu_val); emit memory_rt_value(dt.val_rt); @@ -537,11 +540,12 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { .excause = dt.excause, .in_delay_slot = dt.in_delay_slot, .stop_if = dt.stop_if, + .is_valid = dt.is_valid, }; } void Core::writeback(const struct dtMemory &dt) { - emit writeback_inst_addr_value(dt.inst_addr); + emit writeback_inst_addr_value(dt.is_valid? dt.inst_addr: STAGEADDR_NONE); emit instruction_writeback(dt.inst, dt.inst_addr, dt.excause); emit writeback_value(dt.towrite_val); emit writeback_regw_value(dt.regwrite); @@ -600,6 +604,7 @@ void Core::dtFetchInit(struct dtFetch &dt) { dt.inst = Instruction(0x00); dt.excause = EXCAUSE_NONE; dt.in_delay_slot = false; + dt.is_valid = false; } void Core::dtDecodeInit(struct dtDecode &dt) { @@ -632,6 +637,7 @@ void Core::dtDecodeInit(struct dtDecode &dt) { dt.in_delay_slot = false; dt.stall = false; dt.stop_if = false; + dt.is_valid = false; } void Core::dtExecuteInit(struct dtExecute &dt) { @@ -646,6 +652,7 @@ void Core::dtExecuteInit(struct dtExecute &dt) { dt.excause = EXCAUSE_NONE; dt.in_delay_slot = false; dt.stop_if = false; + dt.is_valid = false; } void Core::dtMemoryInit(struct dtMemory &dt) { @@ -658,6 +665,7 @@ void Core::dtMemoryInit(struct dtMemory &dt) { dt.excause = EXCAUSE_NONE; dt.in_delay_slot = false; dt.stop_if = false; + dt.is_valid = false; } CoreSingle::CoreSingle(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, @@ -742,16 +750,19 @@ void CorePipelined::do_step(bool skip_break) { if (excpt_in_progress) { dtExecuteInit(dt_e); emit instruction_executed(dt_e.inst, dt_e.inst_addr, dt_e.excause); + emit execute_inst_addr_value(STAGEADDR_NONE); } excpt_in_progress = excpt_in_progress || dt_e.excause != EXCAUSE_NONE; if (excpt_in_progress) { dtDecodeInit(dt_d); emit instruction_decoded(dt_d.inst, dt_d.inst_addr, dt_d.excause); + emit decode_inst_addr_value(STAGEADDR_NONE); } excpt_in_progress = excpt_in_progress || dt_e.excause != EXCAUSE_NONE; if (excpt_in_progress) { dtFetchInit(dt_f); emit instruction_fetched(dt_f.inst, dt_f.inst_addr, dt_f.excause); + emit fetch_inst_addr_value(STAGEADDR_NONE); if (dt_m.excause != EXCAUSE_NONE) { regs->pc_abs_jmp(dt_e.inst_addr); handle_exception(this, regs, dt_m.excause, dt_m.inst_addr, @@ -867,6 +878,7 @@ void CorePipelined::do_step(bool skip_break) { if (dt_d.nb_skip_ds) { dtFetchInit(dt_f); emit instruction_fetched(dt_f.inst, dt_f.inst_addr, dt_f.excause); + emit fetch_inst_addr_value(STAGEADDR_NONE); } } } else { diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index 52cadb4..5658726 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -186,6 +186,7 @@ protected: uint32_t inst_addr; // Address of instruction enum ExceptionCause excause; bool in_delay_slot; + bool is_valid; }; struct dtDecode { Instruction inst; @@ -222,6 +223,7 @@ protected: bool in_delay_slot; bool stall; bool stop_if; + bool is_valid; }; struct dtExecute { Instruction inst; @@ -236,6 +238,7 @@ protected: enum ExceptionCause excause; bool in_delay_slot; bool stop_if; + bool is_valid; }; struct dtMemory { Instruction inst; @@ -248,6 +251,7 @@ protected: enum ExceptionCause excause; bool in_delay_slot; bool stop_if; + bool is_valid; }; struct dtFetch fetch(bool skip_break = false); diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index d8219b6..9f85240 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -141,6 +141,8 @@ enum LocationStatus { LOCSTAT_ILLEGAL = 1 << 3, }; +const std::uint32_t STAGEADDR_NONE = 0xffffffff; + } #endif // MACHINEDEFS_H -- cgit v1.2.3