From 54d7ef4272673e55b6a4324373d11875280dad84 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Mon, 11 Feb 2019 22:19:23 +0100 Subject: Display red background for instruction causing exception and skip HW breakpoint for first cycle after resume. Instruction for stage is updated when given stage is flushed as well. But other signals are left intact, it is duty of memory stage to discard effect of instruction causing interrupt. Signed-off-by: Pavel Pisa --- qtmips_gui/coreview/instructionview.cpp | 13 ++++++-- qtmips_gui/coreview/instructionview.h | 4 ++- qtmips_machine/core.cpp | 58 +++++++++++++++++++-------------- qtmips_machine/core.h | 22 ++++++------- qtmips_machine/qtmipsmachine.cpp | 15 +++++++-- qtmips_machine/qtmipsmachine.h | 4 +++ 6 files changed, 74 insertions(+), 42 deletions(-) diff --git a/qtmips_gui/coreview/instructionview.cpp b/qtmips_gui/coreview/instructionview.cpp index d989b7b..495edfb 100644 --- a/qtmips_gui/coreview/instructionview.cpp +++ b/qtmips_gui/coreview/instructionview.cpp @@ -52,7 +52,8 @@ InstructionView::InstructionView() : QGraphicsObject(nullptr), text(this) { f.setPointSize(6); text.setFont(f); - instruction_update(machine::Instruction(), 0); // Initialize to NOP + // Initialize to NOP + instruction_update(machine::Instruction(), 0, machine::EXCAUSE_NONE); } QRectF InstructionView::boundingRect() const { @@ -61,13 +62,19 @@ QRectF InstructionView::boundingRect() const { void InstructionView::paint(QPainter *painter, const QStyleOptionGraphicsItem *option __attribute__((unused)), QWidget *widget __attribute__((unused))) { painter->setPen(QPen(QColor(240, 240, 240))); - painter->setBrush(QBrush(QColor(240, 240, 240))); + if (excause == machine::EXCAUSE_NONE) + painter->setBrush(QBrush(QColor(240, 240, 240))); + else + painter->setBrush(QBrush(QColor(255, 100, 100))); painter->drawRoundRect(-WIDTH/2, 0, WIDTH, HEIGHT, ROUND, ROUND); } -void InstructionView::instruction_update(const machine::Instruction &i, std::uint32_t inst_addr) { +void InstructionView::instruction_update(const machine::Instruction &i, + std::uint32_t inst_addr, machine::ExceptionCause excause) { + QRectF prev_box = boundingRect(); text.setText(i.to_str(inst_addr)); + this->excause = excause; QRectF box = text.boundingRect(); text.setPos(-box.width()/2, GAP); update(prev_box.united(boundingRect())); diff --git a/qtmips_gui/coreview/instructionview.h b/qtmips_gui/coreview/instructionview.h index 8c63fc1..6e39bdd 100644 --- a/qtmips_gui/coreview/instructionview.h +++ b/qtmips_gui/coreview/instructionview.h @@ -51,10 +51,12 @@ public: void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); public slots: - void instruction_update(const machine::Instruction &i, std::uint32_t inst_addr); + void instruction_update(const machine::Instruction &i, std::uint32_t inst_addr, + machine::ExceptionCause excause); private: QGraphicsSimpleTextItem text; + machine::ExceptionCause excause; }; } diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 7c92949..e744848 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -50,9 +50,9 @@ Core::Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, this->hwr_user_local = 0xe0000000; } -void Core::step() { +void Core::step(bool skip_break) { cycle_c++; - do_step(); + do_step(skip_break); } void Core::reset() { @@ -135,17 +135,19 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause, return false; } -struct Core::dtFetch Core::fetch() { +struct Core::dtFetch Core::fetch(bool skip_break) { enum ExceptionCause excause = EXCAUSE_NONE; std::uint32_t inst_addr = regs->read_pc(); - emit fetch_inst_addr_value(inst_addr); Instruction inst(mem_program->read_word(inst_addr)); - emit instruction_fetched(inst, inst_addr); - hwBreak *brk = hw_breaks.value(inst_addr); - if (brk != nullptr) { - excause = EXCAUSE_HWBREAK; + if (!skip_break) { + hwBreak *brk = hw_breaks.value(inst_addr); + if (brk != nullptr) { + excause = EXCAUSE_HWBREAK; + } } + emit fetch_inst_addr_value(inst_addr); + emit instruction_fetched(inst, inst_addr, excause); return { .inst = inst, .inst_addr = inst_addr, @@ -156,8 +158,6 @@ struct Core::dtFetch Core::fetch() { struct Core::dtDecode Core::decode(const struct dtFetch &dt) { uint8_t rwrite; - emit decode_inst_addr_value(dt.inst_addr); - emit instruction_decoded(dt.inst, dt.inst_addr); enum InstructionFlags flags; enum AluOp alu_op; enum AccessControl mem_ctl; @@ -191,6 +191,8 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) { excause = dt.inst.encoded_exception(); } + emit decode_inst_addr_value(dt.inst_addr); + emit instruction_decoded(dt.inst, dt.inst_addr, excause); emit decode_instruction_value(dt.inst.data()); emit decode_reg1_value(val_rs); emit decode_reg2_value(val_rt); @@ -246,8 +248,6 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) { } struct Core::dtExecute Core::execute(const struct dtDecode &dt) { - emit execute_inst_addr_value(dt.inst_addr); - emit instruction_executed(dt.inst, dt.inst_addr); bool discard; // Handle conditional move (we have to change regwrite signal if conditional is not met) @@ -283,6 +283,8 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { } } + emit execute_inst_addr_value(dt.inst_addr); + emit instruction_executed(dt.inst, dt.inst_addr, dt.excause); emit execute_alu_value(alu_val); emit execute_reg1_value(dt.val_rs); emit execute_reg2_value(dt.val_rt); @@ -313,8 +315,6 @@ struct Core::dtExecute Core::execute(const struct dtDecode &dt) { } struct Core::dtMemory Core::memory(const struct dtExecute &dt) { - emit memory_inst_addr_value(dt.inst_addr); - emit instruction_memory(dt.inst, dt.inst_addr); std::uint32_t towrite_val = dt.alu_val; std::uint32_t mem_addr = dt.alu_val; bool memread = dt.memread; @@ -344,6 +344,8 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { } } + emit memory_inst_addr_value(dt.inst_addr); + emit instruction_memory(dt.inst, dt.inst_addr, dt.excause); emit memory_alu_value(dt.alu_val); emit memory_rt_value(dt.val_rt); emit memory_mem_value(memread ? towrite_val : 0); @@ -367,7 +369,7 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { void Core::writeback(const struct dtMemory &dt) { emit writeback_inst_addr_value(dt.inst_addr); - emit instruction_writeback(dt.inst, dt.inst_addr); + emit instruction_writeback(dt.inst, dt.inst_addr, dt.excause); emit writeback_value(dt.towrite_val); emit writeback_regw_value(dt.regwrite); emit writeback_regw_num_value(dt.rwrite); @@ -377,7 +379,7 @@ void Core::writeback(const struct dtMemory &dt) { bool Core::handle_pc(const struct dtDecode &dt) { bool branch = false; - emit instruction_program_counter(dt.inst, dt.inst_addr); + emit instruction_program_counter(dt.inst, dt.inst_addr, EXCAUSE_NONE); if (dt.jump) { if (!dt.bjr_req_rs) { @@ -487,11 +489,11 @@ CoreSingle::~CoreSingle() { delete jmp_delay_decode; } -void CoreSingle::do_step() { +void CoreSingle::do_step(bool skip_break) { bool in_delay_slot = false; std::uint32_t jump_branch_pc; - struct dtFetch f = fetch(); + struct dtFetch f = fetch(skip_break); struct dtDecode d = decode(f); // Handle PC before instruction following jump leaves decode stage @@ -535,7 +537,7 @@ CorePipelined::CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryA reset(); } -void CorePipelined::do_step() { +void CorePipelined::do_step(bool skip_break) { bool stall = false; bool excpt_in_progress = false; std::uint32_t jump_branch_pc = dt_m.inst_addr; @@ -548,14 +550,19 @@ void CorePipelined::do_step() { // Resolve exceptions excpt_in_progress = dt_m.excause != EXCAUSE_NONE; - if (excpt_in_progress) + if (excpt_in_progress) { dtExecuteInit(dt_e); + emit instruction_executed(dt_e.inst, dt_e.inst_addr, dt_e.excause); + } excpt_in_progress = excpt_in_progress || dt_e.excause != EXCAUSE_NONE; - if (excpt_in_progress) + if (excpt_in_progress) { dtDecodeInit(dt_d); + emit instruction_decoded(dt_d.inst, dt_d.inst_addr, dt_d.excause); + } 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); 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, @@ -656,18 +663,21 @@ void CorePipelined::do_step() { // Now process program counter (loop connections from decode stage) if (!stall) { - dt_f = fetch(); + dt_f = fetch(skip_break); if (handle_pc(dt_d)) { dt_f.in_delay_slot = true; } else { - if (dt_d.nb_skip_ds) + if (dt_d.nb_skip_ds) { dtFetchInit(dt_f); + emit instruction_fetched(dt_f.inst, dt_f.inst_addr, dt_f.excause); + } } } else { // Run fetch stage on empty - fetch(); + fetch(skip_break); // clear decode latch (insert nope to execute stage) dtDecodeInit(dt_d); + emit instruction_decoded(dt_d.inst, dt_d.inst_addr, dt_d.excause); } } diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index bd62f52..97a15c1 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -72,7 +72,7 @@ public: Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, unsigned int min_cache_row_size = 1); - void step(); // Do single step + void step(bool skip_break = false); // Do single step void reset(); // Reset core (only core, memory and registers has to be reseted separately) unsigned cycles(); // Returns number of executed cycles @@ -92,12 +92,12 @@ public: }; signals: - void instruction_fetched(const machine::Instruction &inst, std::uint32_t inst_addr); - void instruction_decoded(const machine::Instruction &inst, std::uint32_t inst_addr); - void instruction_executed(const machine::Instruction &inst, std::uint32_t inst_addr); - void instruction_memory(const machine::Instruction &inst, std::uint32_t inst_addr); - void instruction_writeback(const machine::Instruction &inst, std::uint32_t inst_addr); - void instruction_program_counter(const machine::Instruction &inst, std::uint32_t inst_addr); + void instruction_fetched(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); + void instruction_decoded(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); + void instruction_executed(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); + void instruction_memory(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); + void instruction_writeback(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); + void instruction_program_counter(const machine::Instruction &inst, std::uint32_t inst_addr, ExceptionCause excause); void fetch_inst_addr_value(std::uint32_t); void fetch_jump_reg_value(std::uint32_t); @@ -151,7 +151,7 @@ signals: void stop_on_exception_reached(); protected: - virtual void do_step() = 0; + virtual void do_step(bool skip_break = false) = 0; virtual void do_reset() = 0; bool handle_exception(Core *core, Registers *regs, @@ -225,7 +225,7 @@ protected: bool in_delay_slot; }; - struct dtFetch fetch(); + struct dtFetch fetch(bool skip_break = false); struct dtDecode decode(const struct dtFetch&); struct dtExecute execute(const struct dtDecode&); struct dtMemory memory(const struct dtExecute&); @@ -257,7 +257,7 @@ public: ~CoreSingle(); protected: - void do_step(); + void do_step(bool skip_break = false); void do_reset(); private: @@ -269,7 +269,7 @@ public: CorePipelined(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, enum MachineConfig::HazardUnit hazard_unit = MachineConfig::HU_STALL_FORWARD); protected: - void do_step(); + void do_step(bool skip_break = false); void do_reset(); private: diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index 23a83d3..382a9f2 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -68,7 +68,7 @@ QtMipsMachine::QtMipsMachine(const MachineConfig &cc) : QObject(), mcnf(&cc) { run_t = new QTimer(this); set_speed(0); // In default run as fast as possible - connect(run_t, SIGNAL(timeout()), this, SLOT(step())); + connect(run_t, SIGNAL(timeout()), this, SLOT(step_timer())); } QtMipsMachine::~QtMipsMachine() { @@ -150,6 +150,7 @@ void QtMipsMachine::play() { CTL_GUARD; set_status(ST_RUNNING); run_t->start(); + step_internal(true); } void QtMipsMachine::pause() { @@ -159,13 +160,13 @@ void QtMipsMachine::pause() { run_t->stop(); } -void QtMipsMachine::step() { +void QtMipsMachine::step_internal(bool skip_break) { CTL_GUARD; enum Status stat_prev = stat; set_status(ST_BUSY); emit tick(); try { - cr->step(); + cr->step(skip_break); } catch (QtMipsException &e) { run_t->stop(); set_status(ST_TRAPPED); @@ -183,6 +184,14 @@ void QtMipsMachine::step() { emit post_tick(); } +void QtMipsMachine::step() { + step_internal(true); +} + +void QtMipsMachine::step_timer() { + step_internal(); +} + void QtMipsMachine::restart() { pause(); regs->reset(); diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index de5275a..22ba0f9 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -95,7 +95,11 @@ signals: void tick(); // Time tick void post_tick(); // Emitted after tick to allow updates +private slots: + void step_timer(); + private: + void step_internal(bool skip_break = false); MachineConfig mcnf; Registers *regs; -- cgit v1.2.3