From 745a2aff8602a48b723a8d2ebf54b0e92cd17b30 Mon Sep 17 00:00:00 2001 From: Pavel Pisa Date: Mon, 11 Feb 2019 17:44:29 +0100 Subject: Prepare core for "hardware" breakpoints support and add signals to follow stages. Signed-off-by: Pavel Pisa --- qtmips_machine/core.cpp | 56 +++++++++++++++++++++++++++++++++++----- qtmips_machine/core.h | 15 +++++++++++ qtmips_machine/machinedefs.h | 1 + qtmips_machine/qtmipsmachine.cpp | 16 ++++++++++++ qtmips_machine/qtmipsmachine.h | 3 +++ 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/qtmips_machine/core.cpp b/qtmips_machine/core.cpp index 30d01bb..68dbe0b 100644 --- a/qtmips_machine/core.cpp +++ b/qtmips_machine/core.cpp @@ -40,7 +40,7 @@ using namespace machine; Core::Core(Registers *regs, MemoryAccess *mem_program, MemoryAccess *mem_data, - unsigned int min_cache_row_size) : ex_handlers() { + unsigned int min_cache_row_size) : ex_handlers(), hw_breaks() { cycle_c = 0; this->regs = regs; this->mem_program = mem_program; @@ -76,6 +76,28 @@ MemoryAccess *Core::get_mem_program() { return mem_program; } + +Core::hwBreak::hwBreak(std::uint32_t addr) { + this->addr = addr; + flags = 0; + count = 0; +} + +void Core::inser_hwbreak(std::uint32_t address) { + hw_breaks.insert(address, new hwBreak(address)); +} + +void Core::remove_hwbreak(std::uint32_t address) { + hwBreak* hwbrk = hw_breaks.take(address); + if (hwbrk != nullptr) + delete hwbrk; +} + +bool Core::is_hwbreak(std::uint32_t address) { + hwBreak* hwbrk = hw_breaks.value(address); + return hwbrk != nullptr; +} + void Core::register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler) { if (excause == EXCAUSE_NONE ) { @@ -94,6 +116,13 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause, std::uint32_t jump_branch_pc, bool in_delay_slot, std::uint32_t mem_ref_addr) { + if (excause == EXCAUSE_HWBREAK) { + if (in_delay_slot) + regs->pc_abs_jmp(inst_addr); + else + regs->pc_abs_jmp(jump_branch_pc); + } + ExceptionHandler *exhandler = ex_handlers.value(excause); if (exhandler != nullptr) return exhandler->handle_exception(core, regs, excause, inst_addr, @@ -107,19 +136,27 @@ bool Core::handle_exception(Core *core, Registers *regs, ExceptionCause excause, } struct Core::dtFetch Core::fetch() { + 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; + } return { .inst = inst, .inst_addr = inst_addr, - .excause = EXCAUSE_NONE, + .excause = excause, .in_delay_slot = false, }; } 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; @@ -150,9 +187,9 @@ struct Core::dtDecode Core::decode(const struct dtFetch &dt) { else immediate_val = sign_extend(dt.inst.immediate()); - if ((flags & IMF_EXCEPTION) && (excause == EXCAUSE_NONE)) { - excause = dt.inst.encoded_exception(); - } + if ((flags & IMF_EXCEPTION) && (excause == EXCAUSE_NONE)) { + excause = dt.inst.encoded_exception(); + } emit decode_instruction_value(dt.inst.data()); emit decode_reg1_value(val_rs); @@ -209,6 +246,7 @@ 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; @@ -275,6 +313,7 @@ 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; @@ -319,7 +358,7 @@ struct Core::dtMemory Core::memory(const struct dtExecute &dt) { .regwrite = regwrite, .rwrite = dt.rwrite, .towrite_val = towrite_val, - .mem_addr = mem_addr, + .mem_addr = mem_addr, .inst_addr = dt.inst_addr, .excause = dt.excause, .in_delay_slot = dt.in_delay_slot, @@ -327,6 +366,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 writeback_value(dt.towrite_val); emit writeback_regw_value(dt.regwrite); @@ -464,8 +504,10 @@ void CoreSingle::do_step() { } jump_branch_pc = jmp_delay_decode->inst_addr; *jmp_delay_decode = d; // Copy current decode - } else + } else { handle_pc(d); + jump_branch_pc = d.inst_addr; + } struct dtExecute e = execute(d); struct dtMemory m = memory(e); diff --git a/qtmips_machine/core.h b/qtmips_machine/core.h index 3303438..88d0e9b 100644 --- a/qtmips_machine/core.h +++ b/qtmips_machine/core.h @@ -81,6 +81,9 @@ public: MemoryAccess *get_mem_data(); MemoryAccess *get_mem_program(); void register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler); + void inser_hwbreak(std::uint32_t address); + void remove_hwbreak(std::uint32_t address); + bool is_hwbreak(std::uint32_t address); enum ForwardFrom { FORWARD_NONE = 0b00, @@ -96,9 +99,11 @@ signals: 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 fetch_inst_addr_value(std::uint32_t); void fetch_jump_reg_value(std::uint32_t); void fetch_jump_value(std::uint32_t); void fetch_branch_value(std::uint32_t); + void decode_inst_addr_value(std::uint32_t); void decode_instruction_value(std::uint32_t); void decode_reg1_value(std::uint32_t); void decode_reg2_value(std::uint32_t); @@ -115,6 +120,7 @@ signals: void decode_regd31_value(std::uint32_t); void forward_m_d_rs_value(std::uint32_t); void forward_m_d_rt_value(std::uint32_t); + void execute_inst_addr_value(std::uint32_t); void execute_alu_value(std::uint32_t); void execute_reg1_value(std::uint32_t); void execute_reg2_value(std::uint32_t); @@ -128,6 +134,7 @@ signals: void execute_alusrc_value(std::uint32_t); void execute_regdest_value(std::uint32_t); void execute_regw_num_value(std::uint32_t); + void memory_inst_addr_value(std::uint32_t); void memory_alu_value(std::uint32_t); void memory_rt_value(std::uint32_t); void memory_mem_value(std::uint32_t); @@ -136,6 +143,7 @@ signals: void memory_memwrite_value(std::uint32_t); void memory_memread_value(std::uint32_t); void memory_regw_num_value(std::uint32_t); + void writeback_inst_addr_value(std::uint32_t); void writeback_value(std::uint32_t); void writeback_regw_value(std::uint32_t); void writeback_regw_num_value(std::uint32_t); @@ -231,9 +239,16 @@ protected: void dtMemoryInit(struct dtMemory &dt); private: + struct hwBreak{ + hwBreak(std::uint32_t addr); + std::uint32_t addr; + unsigned int flags; + unsigned int count; + }; unsigned int cycle_c; unsigned int min_cache_row_size; std::uint32_t hwr_user_local; + QMap hw_breaks; }; class CoreSingle : public Core { diff --git a/qtmips_machine/machinedefs.h b/qtmips_machine/machinedefs.h index 05bf103..258b76c 100644 --- a/qtmips_machine/machinedefs.h +++ b/qtmips_machine/machinedefs.h @@ -56,6 +56,7 @@ enum ExceptionCause { EXCAUSE_NONE, EXCAUSE_BREAK, EXCAUSE_SYSCALL, + EXCAUSE_HWBREAK, }; enum AluOp : std::uint8_t { diff --git a/qtmips_machine/qtmipsmachine.cpp b/qtmips_machine/qtmipsmachine.cpp index 2942bec..f846ed2 100644 --- a/qtmips_machine/qtmipsmachine.cpp +++ b/qtmips_machine/qtmipsmachine.cpp @@ -205,3 +205,19 @@ void QtMipsMachine::register_exception_handler(ExceptionCause excause, if (cr != nullptr) cr->register_exception_handler(excause, exhandler); } + +void QtMipsMachine::inser_hwbreak(std::uint32_t address) { + if (cr != nullptr) + cr->inser_hwbreak(address); +} + +void QtMipsMachine::remove_hwbreak(std::uint32_t address) { + if (cr != nullptr) + cr->remove_hwbreak(address); +} + +bool QtMipsMachine::is_hwbreak(std::uint32_t address) { + if (cr != nullptr) + return cr->is_hwbreak(address); + return false; +} diff --git a/qtmips_machine/qtmipsmachine.h b/qtmips_machine/qtmipsmachine.h index 7a128f6..82245ff 100644 --- a/qtmips_machine/qtmipsmachine.h +++ b/qtmips_machine/qtmipsmachine.h @@ -78,6 +78,9 @@ public: bool exited(); void register_exception_handler(ExceptionCause excause, ExceptionHandler *exhandler); + void inser_hwbreak(std::uint32_t address); + void remove_hwbreak(std::uint32_t address); + bool is_hwbreak(std::uint32_t address); public slots: void play(); -- cgit v1.2.3